Import Tint changes from Dawn
Changes:
- d4908670e1773c358d178b116e308e06262d9683 tint: clean up const eval test framework by Antonio Maiorano <amaiorano@google.com>
- 8392a82a40b73685a9832d42556efd7c43e4951e Const eval for `normalize` by dan sinclair <dsinclair@chromium.org>
- 91ad2bc3846280f5c4679ee6b2168fa0ff0e6656 Remove support for SPIRV-Tools API transition by David Neto <dneto@google.com>
- 724ad2a290af41acaa6a6d390412a6d460638f8c Const eval for `fma` by dan sinclair <dsinclair@chromium.org>
- a2a88950200c553e6bcce254fb4515c08f876b69 Const eval for `distance` by dan sinclair <dsinclair@chromium.org>
- 7736153c1505431d8d9b044af2decef04bac1fee Const eval for `inverseSqrt` by dan sinclair <dsinclair@chromium.org>
- ab9b5f3aa5996054993f01914fe5a6833a2c8e38 Tint: Implement f16 in uniform and storage address space by Zhaoming Jiang <zhaoming.jiang@intel.com>
- 9ba5f9e2c6406ec15e9a8d1390843aa4606a78ae tint: const eval of transpose builtin by Antonio Maiorano <amaiorano@google.com>
- b785dc1e3961c664cbd8b0b6d2d181af5b15f7b3 Update parser to match * and & spec change. by dan sinclair <dsinclair@chromium.org>
- 7c6e229a18cab18b1a069cb83f91809819e32828 tint/utils: Make Hashmap::Find() safer to use by Ben Clayton <bclayton@google.com>
- 597ad53029a2d0834da2b799d586beb7d0379b68 tint/transform: Add HoistToDeclBefore::VariableKind by Ben Clayton <bclayton@google.com>
- ed998e91ab43fa7a9e62f8e716af7b058305aae3 tint: Suffix builtin return types with '_f32' by Ben Clayton <bclayton@google.com>
- 05c8daac420965194364a6647bfadf5322c284c2 tint: const eval of determinant builtin by Antonio Maiorano <amaiorano@google.com>
- 5180be6b1d1248542573cad51b5283810b9c4fcf Remove reserved words. by dan sinclair <dsinclair@chromium.org>
- 69c2c34326e09ced925cea219e3e5da22f42d1bb tint: Implement const-eval of frexp() by Ben Clayton <bclayton@google.com>
- f2ad5fd260505911d3cd51bafc9142b7ee9baecb Add const-eval for `log` and `log2`. by dan sinclair <dsinclair@chromium.org>
- ae739d6d1cf29d1ca45e4a2b5840fa7f3f2b003f Add const-eval for `exp` and `exp2`. by dan sinclair <dsinclair@chromium.org>
- 47fb4f9c5738e8c6e94f042e35e8b064f7fe5c67 tint/ir: fix double-underscore in identifier by Ben Clayton <bclayton@google.com>
- 31b7fca82c312035917f2168cb40d6d0966c1607 tint: Add abstract overload of modf by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: d4908670e1773c358d178b116e308e06262d9683
Change-Id: I533b0650df13fee8e7175bfb407677d64bd30541
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/109580
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Reviewed-by: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 491fd7d..3741764 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -1246,6 +1246,8 @@
"transform/single_entry_point_test.cc",
"transform/spirv_atomic_test.cc",
"transform/std140_exhaustive_test.cc",
+ "transform/std140_f16_test.cc",
+ "transform/std140_f32_test.cc",
"transform/std140_test.cc",
"transform/substitute_override_test.cc",
"transform/test_helper.h",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index dfe9433..a8644b7 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -1212,6 +1212,8 @@
transform/single_entry_point_test.cc
transform/spirv_atomic_test.cc
transform/std140_exhaustive_test.cc
+ transform/std140_f16_test.cc
+ transform/std140_f32_test.cc
transform/std140_test.cc
transform/substitute_override_test.cc
transform/test_helper.h
diff --git a/src/tint/clone_context.cc b/src/tint/clone_context.cc
index 457522b..fe94a14 100644
--- a/src/tint/clone_context.cc
+++ b/src/tint/clone_context.cc
@@ -73,7 +73,7 @@
}
// Was Replace() called for this object?
- if (auto* fn = replacements_.Find(object)) {
+ if (auto fn = replacements_.Find(object)) {
return (*fn)();
}
diff --git a/src/tint/clone_context.h b/src/tint/clone_context.h
index 05f4868..f1db617 100644
--- a/src/tint/clone_context.h
+++ b/src/tint/clone_context.h
@@ -208,7 +208,7 @@
to.Push(CheckedCast<T>(builder()));
}
for (auto& el : from) {
- if (auto* insert_before = transforms->insert_before_.Find(el)) {
+ if (auto insert_before = transforms->insert_before_.Find(el)) {
for (auto& builder : *insert_before) {
to.Push(CheckedCast<T>(builder()));
}
@@ -216,7 +216,7 @@
if (!transforms->remove_.Contains(el)) {
to.Push(Clone(el));
}
- if (auto* insert_after = transforms->insert_after_.Find(el)) {
+ if (auto insert_after = transforms->insert_after_.Find(el)) {
for (auto& builder : *insert_after) {
to.Push(CheckedCast<T>(builder()));
}
@@ -232,7 +232,7 @@
// Clone(el) may have updated the transformation list, adding an `insert_after`
// transform for `from`.
if (transforms) {
- if (auto* insert_after = transforms->insert_after_.Find(el)) {
+ if (auto insert_after = transforms->insert_after_.Find(el)) {
for (auto& builder : *insert_after) {
to.Push(CheckedCast<T>(builder()));
}
@@ -389,7 +389,7 @@
return *this;
}
- list_transforms_.Edit(&vector).remove_.Add(object);
+ list_transforms_.GetOrZero(&vector)->remove_.Add(object);
return *this;
}
@@ -411,7 +411,7 @@
/// @returns this CloneContext so calls can be chained
template <typename T, size_t N, typename BUILDER>
CloneContext& InsertFront(const utils::Vector<T, N>& vector, BUILDER&& builder) {
- list_transforms_.Edit(&vector).insert_front_.Push(std::forward<BUILDER>(builder));
+ list_transforms_.GetOrZero(&vector)->insert_front_.Push(std::forward<BUILDER>(builder));
return *this;
}
@@ -434,7 +434,7 @@
/// @returns this CloneContext so calls can be chained
template <typename T, size_t N, typename BUILDER>
CloneContext& InsertBack(const utils::Vector<T, N>& vector, BUILDER&& builder) {
- list_transforms_.Edit(&vector).insert_back_.Push(std::forward<BUILDER>(builder));
+ list_transforms_.GetOrZero(&vector)->insert_back_.Push(std::forward<BUILDER>(builder));
return *this;
}
@@ -456,7 +456,7 @@
return *this;
}
- list_transforms_.Edit(&vector).insert_before_.GetOrZero(before).Push(
+ list_transforms_.GetOrZero(&vector)->insert_before_.GetOrZero(before)->Push(
[object] { return object; });
return *this;
}
@@ -475,7 +475,7 @@
CloneContext& InsertBefore(const utils::Vector<T, N>& vector,
const BEFORE* before,
BUILDER&& builder) {
- list_transforms_.Edit(&vector).insert_before_.GetOrZero(before).Push(
+ list_transforms_.GetOrZero(&vector)->insert_before_.GetOrZero(before)->Push(
std::forward<BUILDER>(builder));
return *this;
}
@@ -498,7 +498,7 @@
return *this;
}
- list_transforms_.Edit(&vector).insert_after_.GetOrZero(after).Push(
+ list_transforms_.GetOrZero(&vector)->insert_after_.GetOrZero(after)->Push(
[object] { return object; });
return *this;
}
@@ -517,7 +517,7 @@
CloneContext& InsertAfter(const utils::Vector<T, N>& vector,
const AFTER* after,
BUILDER&& builder) {
- list_transforms_.Edit(&vector).insert_after_.GetOrZero(after).Push(
+ list_transforms_.GetOrZero(&vector)->insert_after_.GetOrZero(after)->Push(
std::forward<BUILDER>(builder));
return *this;
}
@@ -601,61 +601,6 @@
/// @returns the diagnostic list of #dst
diag::List& Diagnostics() const;
- /// VectorListTransforms is a map of utils::Vector pointer to transforms for that list
- struct VectorListTransforms {
- using Map = utils::Hashmap<const void*, ListTransforms, 4>;
-
- /// An accessor to the VectorListTransforms map.
- /// Index caches the last map lookup, and will only re-search the map if the transform map
- /// was modified since the last lookup.
- struct Index {
- /// @returns true if the map now holds a value for the index
- operator bool() {
- Update();
- return cached_;
- }
-
- /// @returns a pointer to the indexed map entry
- const ListTransforms* operator->() {
- Update();
- return cached_;
- }
-
- private:
- friend VectorListTransforms;
-
- Index(const void* list, Map* map)
- : list_(list),
- map_(map),
- generation_(map->Generation()),
- cached_(map_->Find(list)) {}
-
- void Update() {
- if (map_->Generation() != generation_) {
- cached_ = map_->Find(list_);
- generation_ = map_->Generation();
- }
- }
-
- const void* list_;
- Map* map_;
- uint64_t generation_;
- const ListTransforms* cached_;
- };
-
- /// Edit returns a reference to the ListTransforms for the given vector pointer and
- /// increments #list_transform_generation_ signalling that the list transforms have been
- /// modified.
- inline ListTransforms& Edit(const void* list) { return map_.GetOrZero(list); }
-
- /// @returns an Index to the transforms for the given list.
- inline Index Find(const void* list) { return Index{list, &map_}; }
-
- private:
- /// The map of vector pointer to ListTransforms
- Map map_;
- };
-
/// A map of object in #src to functions that create their replacement in #dst
utils::Hashmap<const Cloneable*, std::function<const Cloneable*()>, 8> replacements_;
@@ -666,7 +611,7 @@
utils::Vector<CloneableTransform, 8> transforms_;
/// Transformations to apply to vectors
- VectorListTransforms list_transforms_;
+ utils::Hashmap<const void*, ListTransforms, 4> list_transforms_;
/// Symbol transform registered with ReplaceAll()
SymbolTransform symbol_transform_;
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index da58aea..a148d4d 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -442,9 +442,9 @@
@const fn cross<T: fa_f32_f16>(vec3<T>, vec3<T>) -> vec3<T>
@const fn degrees<T: fa_f32_f16>(T) -> T
@const fn degrees<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
-fn determinant<N: num, T: f32_f16>(mat<N, N, T>) -> T
-fn distance<T: f32_f16>(T, T) -> T
-fn distance<N: num, T: f32_f16>(vec<N, T>, vec<N, T>) -> T
+@const fn determinant<N: num, T: fa_f32_f16>(mat<N, N, T>) -> T
+@const fn distance<T: fa_f32_f16>(T, T) -> T
+@const fn distance<N: num, T: fa_f32_f16>(vec<N, T>, vec<N, T>) -> T
@const fn dot<N: num, T: fia_fiu32_f16>(vec<N, T>, vec<N, T>) -> T
fn dot4I8Packed(u32, u32) -> i32
fn dot4U8Packed(u32, u32) -> u32
@@ -460,10 +460,10 @@
@stage("fragment") fn dpdyCoarse<N: num>(vec<N, f32>) -> vec<N, f32>
@stage("fragment") fn dpdyFine(f32) -> f32
@stage("fragment") fn dpdyFine<N: num>(vec<N, f32>) -> vec<N, f32>
-fn exp<T: f32_f16>(T) -> T
-fn exp<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
-fn exp2<T: f32_f16>(T) -> T
-fn exp2<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
+@const fn exp<T: fa_f32_f16>(T) -> T
+@const fn exp<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
+@const fn exp2<T: fa_f32_f16>(T) -> T
+@const fn exp2<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
@const fn extractBits<T: iu32>(T, u32, u32) -> T
@const fn extractBits<N: num, T: iu32>(vec<N, T>, u32, u32) -> vec<N, T>
fn faceForward<N: num, T: f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T>
@@ -473,12 +473,12 @@
@const fn firstTrailingBit<N: num, T: iu32>(vec<N, T>) -> vec<N, T>
@const fn floor<T: fa_f32_f16>(@test_value(1.5) T) -> T
@const fn floor<N: num, T: fa_f32_f16>(@test_value(1.5) vec<N, T>) -> vec<N, T>
-fn fma<T: f32_f16>(T, T, T) -> T
-fn fma<N: num, T: f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T>
+@const fn fma<T: fa_f32_f16>(T, T, T) -> T
+@const fn fma<N: num, T: fa_f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T>
fn fract<T: f32_f16>(T) -> T
fn fract<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
-fn frexp<T: f32_f16>(T) -> __frexp_result<T>
-fn frexp<N: num, T: f32_f16>(vec<N, T>) -> __frexp_result_vec<N, T>
+@const fn frexp<T: fa_f32_f16>(T) -> __frexp_result<T>
+@const fn frexp<N: num, T: fa_f32_f16>(vec<N, T>) -> __frexp_result_vec<N, T>
@stage("fragment") fn fwidth(f32) -> f32
@stage("fragment") fn fwidth<N: num>(vec<N, f32>) -> vec<N, f32>
@stage("fragment") fn fwidthCoarse(f32) -> f32
@@ -487,16 +487,16 @@
@stage("fragment") fn fwidthFine<N: num>(vec<N, f32>) -> vec<N, f32>
@const fn insertBits<T: iu32>(T, T, u32, u32) -> T
@const fn insertBits<N: num, T: iu32>(vec<N, T>, vec<N, T>, u32, u32) -> vec<N, T>
-fn inverseSqrt<T: f32_f16>(T) -> T
-fn inverseSqrt<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
+@const fn inverseSqrt<T: fa_f32_f16>(T) -> T
+@const fn inverseSqrt<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
fn ldexp<T: f32_f16>(T, i32) -> T
fn ldexp<N: num, T: f32_f16>(vec<N, T>, vec<N, i32>) -> vec<N, T>
@const fn length<T: fa_f32_f16>(@test_value(0.0) T) -> T
@const fn length<N: num, T: fa_f32_f16>(@test_value(0.0) vec<N, T>) -> T
-fn log<T: f32_f16>(T) -> T
-fn log<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
-fn log2<T: f32_f16>(T) -> T
-fn log2<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
+@const fn log<T: fa_f32_f16>(T) -> T
+@const fn log<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
+@const fn log2<T: fa_f32_f16>(T) -> T
+@const fn log2<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
@const fn max<T: fia_fiu32_f16>(T, T) -> T
@const fn max<N: num, T: fia_fiu32_f16>(vec<N, T>, vec<N, T>) -> vec<N, T>
@const fn min<T: fia_fiu32_f16>(T, T) -> T
@@ -504,9 +504,9 @@
fn mix<T: f32_f16>(T, T, T) -> T
fn mix<N: num, T: f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T>
fn mix<N: num, T: f32_f16>(vec<N, T>, vec<N, T>, T) -> vec<N, T>
-@const fn modf<T: f32_f16>(@test_value(-1.5) T) -> __modf_result<T>
-@const fn modf<N: num, T: f32_f16>(@test_value(-1.5) vec<N, T>) -> __modf_result_vec<N, T>
-fn normalize<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
+@const fn modf<T: fa_f32_f16>(@test_value(-1.5) T) -> __modf_result<T>
+@const fn modf<N: num, T: fa_f32_f16>(@test_value(-1.5) vec<N, T>) -> __modf_result_vec<N, T>
+@const fn normalize<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
@const fn pack2x16float(vec2<f32>) -> u32
@const fn pack2x16snorm(vec2<f32>) -> u32
@const fn pack2x16unorm(vec2<f32>) -> u32
@@ -546,7 +546,7 @@
@const fn tan<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
@const fn tanh<T: fa_f32_f16>(T) -> T
@const fn tanh<N: num, T: fa_f32_f16>(vec<N, T>) -> vec<N, T>
-fn transpose<M: num, N: num, T: f32_f16>(mat<M, N, T>) -> mat<N, M, T>
+@const fn transpose<M: num, N: num, T: fa_f32_f16>(mat<M, N, T>) -> mat<N, M, T>
@const fn trunc<T: fa_f32_f16>(@test_value(1.5) T) -> T
@const fn trunc<N: num, T: fa_f32_f16>(@test_value(1.5) vec<N, T>) -> vec<N, T>
@const fn unpack2x16float(u32) -> vec2<f32>
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index 88e2e69..a648d68 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -26,15 +26,15 @@
class ScopedStopNode {
public:
- ScopedStopNode(std::unordered_set<const FlowNode*>* stop_nodes_, const FlowNode* node)
- : stop_nodes__(stop_nodes_), node_(node) {
- stop_nodes__->insert(node_);
+ ScopedStopNode(std::unordered_set<const FlowNode*>* stop_nodes, const FlowNode* node)
+ : stop_nodes_(stop_nodes), node_(node) {
+ stop_nodes_->insert(node_);
}
- ~ScopedStopNode() { stop_nodes__->erase(node_); }
+ ~ScopedStopNode() { stop_nodes_->erase(node_); }
private:
- std::unordered_set<const FlowNode*>* stop_nodes__;
+ std::unordered_set<const FlowNode*>* stop_nodes_;
const FlowNode* node_;
};
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index f97d169..d2edcaf 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -143,83 +143,19 @@
namespace tint::reader::spirv {
-namespace three_sided_patch_function_cc {
-// This machinery is only used while SPIRV-Tools is in transition before it fully
-// uses the C++11 header spirv.hpp11
-
-/// Typedef for pointer to member function while the API call uses
-/// SpvStorageClass for its second argument.
-typedef uint32_t (
- spvtools::opt::analysis::TypeManager::*PointerFinderSpvStorageClass)(uint32_t, SpvStorageClass);
-/// Typedef for pointer to member function while the API call uses
-/// spv::StorageClass for its second argument.
-typedef uint32_t (spvtools::opt::analysis::TypeManager::*PointerFinderSpvStorageClassCpp11)(
- uint32_t,
- spv::StorageClass);
-
-/// @param type_manager the SPIRV-Tools optimizer's type manager
-/// @param finder a pointer to member function in the type manager that does the
-/// actual lookup
-/// @param pointee_type_id the ID of the pointee type
-/// @param sc the storage class. SC can be SpvStorageClass or spv::StorageClass
-/// @returns the ID for a SPIR-V pointer to pointee_type_id in storage class sc
-template <typename FinderType, typename SC>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_manager,
- FinderType finder,
- uint32_t pointee_type_id,
- SC sc);
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClass finder,
- uint32_t pointee_type_id,
- SpvStorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, sc);
-}
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClass finder,
- uint32_t pointee_type_id,
- spv::StorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, static_cast<SpvStorageClass>(sc));
-}
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClassCpp11 finder,
- uint32_t pointee_type_id,
- SpvStorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, static_cast<spv::StorageClass>(sc));
-}
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClassCpp11 finder,
- uint32_t pointee_type_id,
- spv::StorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, sc);
-}
-} // namespace three_sided_patch_function_cc
-
namespace {
constexpr uint32_t kMaxVectorLen = 4;
-template <typename FromOpcodeType>
-spv::Op ToOpcode(FromOpcodeType oc) {
- return static_cast<spv::Op>(oc);
-}
-
/// @param inst a SPIR-V instruction
/// @returns Returns the opcode for an instruciton
inline spv::Op opcode(const spvtools::opt::Instruction& inst) {
- return ToOpcode(inst.opcode());
+ return inst.opcode();
}
/// @param inst a SPIR-V instruction pointer
/// @returns Returns the opcode for an instruciton
inline spv::Op opcode(const spvtools::opt::Instruction* inst) {
- return ToOpcode(inst->opcode());
+ return inst->opcode();
}
// Gets the AST unary opcode for the given SPIR-V opcode, if any
@@ -727,7 +663,7 @@
// Visit successors. We will naturally skip the continue target and merge
// blocks.
auto* terminator = bb->terminator();
- auto opcode = ToOpcode(terminator->opcode());
+ const auto opcode = terminator->opcode();
if (opcode == spv::Op::OpBranchConditional) {
// Visit the false branch, then the true branch, to make them come
// out in the natural order for an "if".
@@ -3522,7 +3458,7 @@
const auto phi_id = assignment.phi_id;
auto* const lhs_expr = builder_.Expr(namer_.Name(phi_id));
// If RHS value is actually a phi we just cpatured, then use it.
- auto* const copy_sym = copied_phis.Find(assignment.value_id);
+ auto copy_sym = copied_phis.Find(assignment.value_id);
auto* const rhs_expr =
copy_sym ? builder_.Expr(*copy_sym) : MakeExpression(assignment.value_id).expr;
AddStatement(builder_.Assign(lhs_expr, rhs_expr));
@@ -4611,9 +4547,7 @@
<< ": " << pointee_type_inst->PrettyPrint();
return {};
}
- const auto pointer_type_id = three_sided_patch_function_cc::FindPointerToType(
- type_mgr_, &spvtools::opt::analysis::TypeManager::FindPointerToType, pointee_type_id,
- address_space);
+ const auto pointer_type_id = type_mgr_->FindPointerToType(pointee_type_id, address_space);
auto* type = parser_impl_.ConvertType(pointer_type_id, PtrAs::Ref);
TINT_ASSERT(Reader, type && type->Is<Reference>());
current_expr = TypedExpression{type, next_expr};
diff --git a/src/tint/reader/spirv/parser_impl.cc b/src/tint/reader/spirv/parser_impl.cc
index 600e570..52bdb12 100644
--- a/src/tint/reader/spirv/parser_impl.cc
+++ b/src/tint/reader/spirv/parser_impl.cc
@@ -34,65 +34,6 @@
namespace tint::reader::spirv {
-namespace three_sided_patch {
-// This machinery is only used while SPIRV-Tools is in transition before it fully
-// uses the C++11 header spirv.hpp11
-
-/// Typedef for pointer to member function while the API call uses
-/// SpvStorageClass for its second argument.
-typedef uint32_t (
- spvtools::opt::analysis::TypeManager::*PointerFinderSpvStorageClass)(uint32_t, SpvStorageClass);
-/// Typedef for pointer to member function while the API call uses
-/// spv::StorageClass for its second argument.
-typedef uint32_t (spvtools::opt::analysis::TypeManager::*PointerFinderSpvStorageClassCpp11)(
- uint32_t,
- spv::StorageClass);
-
-/// @param type_manager the SPIRV-Tools optimizer's type manager
-/// @param finder a pointer to member function in the type manager that does the
-/// actual lookup
-/// @param pointee_type_id the ID of the pointee type
-/// @param sc the storage class. SC can be SpvStorageClass or spv::StorageClass
-/// @returns the ID for a SPIR-V pointer to pointee_type_id in storage class sc
-template <typename FinderType, typename SC>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_manager,
- FinderType finder,
- uint32_t pointee_type_id,
- SC sc);
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClass finder,
- uint32_t pointee_type_id,
- SpvStorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, sc);
-}
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClass finder,
- uint32_t pointee_type_id,
- spv::StorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, static_cast<SpvStorageClass>(sc));
-}
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClassCpp11 finder,
- uint32_t pointee_type_id,
- SpvStorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, static_cast<spv::StorageClass>(sc));
-}
-
-template <>
-uint32_t FindPointerToType(spvtools::opt::analysis::TypeManager* type_mgr,
- PointerFinderSpvStorageClassCpp11 finder,
- uint32_t pointee_type_id,
- spv::StorageClass sc) {
- return (type_mgr->*finder)(pointee_type_id, sc);
-}
-} // namespace three_sided_patch
-
namespace {
// Input SPIR-V needs only to conform to Vulkan 1.1 requirements.
@@ -104,12 +45,12 @@
/// @param inst a SPIR-V instruction
/// @returns Returns the opcode for an instruciton
inline spv::Op opcode(const spvtools::opt::Instruction& inst) {
- return static_cast<spv::Op>(inst.opcode());
+ return inst.opcode();
}
/// @param inst a SPIR-V instruction pointer
/// @returns Returns the opcode for an instruciton
inline spv::Op opcode(const spvtools::opt::Instruction* inst) {
- return static_cast<spv::Op>(inst->opcode());
+ return inst->opcode();
}
// A FunctionTraverser is used to compute an ordering of functions in the
@@ -1347,8 +1288,7 @@
// Manufacture a type for the gl_Position variable if we have to.
if ((builtin_position_.struct_type_id != 0) &&
(builtin_position_.position_member_pointer_type_id == 0)) {
- builtin_position_.position_member_pointer_type_id = three_sided_patch::FindPointerToType(
- type_mgr_, &spvtools::opt::analysis::TypeManager::FindPointerToType,
+ builtin_position_.position_member_pointer_type_id = type_mgr_->FindPointerToType(
builtin_position_.position_member_type_id, builtin_position_.storage_class);
ConvertType(builtin_position_.position_member_pointer_type_id);
}
diff --git a/src/tint/reader/spirv/parser_impl.h b/src/tint/reader/spirv/parser_impl.h
index 1780ca3..9ff9033 100644
--- a/src/tint/reader/spirv/parser_impl.h
+++ b/src/tint/reader/spirv/parser_impl.h
@@ -666,7 +666,7 @@
/// @param id a SPIR-V ID
/// @returns the AST variable or null.
const ast::Var* GetModuleVariable(uint32_t id) {
- auto* entry = module_variable_.Find(id);
+ auto entry = module_variable_.Find(id);
return entry ? *entry : nullptr;
}
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index 6314133..49e266f 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -87,24 +87,23 @@
t == "goto" || t == "groupshared" || t == "handle" || t == "highp" || t == "impl" ||
t == "implements" || t == "import" || t == "inline" || t == "inout" ||
t == "instanceof" || t == "interface" || t == "invariant" || t == "layout" ||
- t == "line" || t == "lineadj" || t == "lowp" || t == "macro" || t == "macro_rules" ||
- t == "match" || t == "mediump" || t == "meta" || t == "mod" || t == "module" ||
- t == "move" || t == "mut" || t == "mutable" || t == "namespace" || t == "new" ||
- t == "nil" || t == "noexcept" || t == "noinline" || t == "nointerpolation" ||
- t == "noperspective" || t == "null" || t == "nullptr" || t == "of" || t == "operator" ||
- t == "package" || t == "packoffset" || t == "partition" || t == "pass" || t == "patch" ||
- t == "pixelfragment" || t == "point" || t == "precise" || t == "precision" ||
- t == "premerge" || t == "priv" || t == "protected" || t == "pub" || t == "public" ||
- t == "readonly" || t == "ref" || t == "regardless" || t == "register" ||
- t == "reinterpret_cast" || t == "requires" || t == "resource" || t == "restrict" ||
- t == "self" || t == "set" || t == "shared" || t == "signed" || t == "sizeof" ||
- t == "smooth" || t == "snorm" || t == "static" || t == "static_cast" || t == "std" ||
- t == "subroutine" || t == "super" || t == "target" || t == "template" || t == "this" ||
- t == "thread_local" || t == "throw" || t == "trait" || t == "try" || t == "typedef" ||
- t == "typeid" || t == "typename" || t == "typeof" || t == "union" || t == "unless" ||
- t == "unorm" || t == "unsafe" || t == "unsized" || t == "use" || t == "using" ||
- t == "varying" || t == "virtual" || t == "volatile" || t == "wgsl" || t == "where" ||
- t == "with" || t == "writeonly" || t == "yield";
+ t == "lowp" || t == "macro" || t == "macro_rules" || t == "match" || t == "mediump" ||
+ t == "meta" || t == "mod" || t == "module" || t == "move" || t == "mut" ||
+ t == "mutable" || t == "namespace" || t == "new" || t == "nil" || t == "noexcept" ||
+ t == "noinline" || t == "nointerpolation" || t == "noperspective" || t == "null" ||
+ t == "nullptr" || t == "of" || t == "operator" || t == "package" || t == "packoffset" ||
+ t == "partition" || t == "pass" || t == "patch" || t == "pixelfragment" ||
+ t == "precise" || t == "precision" || t == "premerge" || t == "priv" ||
+ t == "protected" || t == "pub" || t == "public" || t == "readonly" || t == "ref" ||
+ t == "regardless" || t == "register" || t == "reinterpret_cast" || t == "requires" ||
+ t == "resource" || t == "restrict" || t == "self" || t == "set" || t == "shared" ||
+ t == "signed" || t == "sizeof" || t == "smooth" || t == "snorm" || t == "static" ||
+ t == "static_cast" || t == "std" || t == "subroutine" || t == "super" || t == "target" ||
+ t == "template" || t == "this" || t == "thread_local" || t == "throw" || t == "trait" ||
+ t == "try" || t == "typedef" || t == "typeid" || t == "typename" || t == "typeof" ||
+ t == "union" || t == "unless" || t == "unorm" || t == "unsafe" || t == "unsized" ||
+ t == "use" || t == "using" || t == "varying" || t == "virtual" || t == "volatile" ||
+ t == "wgsl" || t == "where" || t == "with" || t == "writeonly" || t == "yield";
}
/// Enter-exit counters for block token types.
@@ -3228,47 +3227,46 @@
}
// lhs_expression
-// : ( STAR | AND )* core_lhs_expression component_or_swizzle_specifier?
+// : core_lhs_expression component_or_swizzle_specifier ?
+// | AND lhs_expression
+// | STAR lhs_expression
Maybe<const ast::Expression*> ParserImpl::lhs_expression() {
- std::vector<const Token*> prefixes;
- while (peek_is(Token::Type::kStar) || peek_is(Token::Type::kAnd) ||
- peek_is(Token::Type::kAndAnd)) {
- auto& t = next();
-
- // If an '&&' is provided split into '&' and '&'
- if (t.Is(Token::Type::kAndAnd)) {
- split_token(Token::Type::kAnd, Token::Type::kAnd);
- }
-
- prefixes.push_back(&t);
- }
-
auto core_expr = core_lhs_expression();
if (core_expr.errored) {
return Failure::kErrored;
- } else if (!core_expr.matched) {
- if (prefixes.empty()) {
- return Failure::kNoMatch;
+ }
+ if (core_expr.matched) {
+ return component_or_swizzle_specifier(core_expr.value);
+ }
+
+ auto check_lhs = [&](ast::UnaryOp op) -> Maybe<const ast::Expression*> {
+ auto& t = peek();
+ auto expr = lhs_expression();
+ if (expr.errored) {
+ return Failure::kErrored;
}
-
- return add_error(peek(), "missing expression");
- }
-
- const auto* expr = core_expr.value;
- for (auto it = prefixes.rbegin(); it != prefixes.rend(); ++it) {
- auto& t = **it;
- ast::UnaryOp op = ast::UnaryOp::kAddressOf;
- if (t.Is(Token::Type::kStar)) {
- op = ast::UnaryOp::kIndirection;
+ if (!expr.matched) {
+ return add_error(t, "missing expression");
}
- expr = create<ast::UnaryOpExpression>(t.source(), op, expr);
+ return create<ast::UnaryOpExpression>(t.source(), op, expr.value);
+ };
+
+ // If an `&&` is encountered, split it into two `&`'s
+ if (match(Token::Type::kAndAnd)) {
+ // The first `&` is consumed as part of the `&&`, so this needs to run the check itself.
+ split_token(Token::Type::kAnd, Token::Type::kAnd);
+ return check_lhs(ast::UnaryOp::kAddressOf);
}
- auto e = component_or_swizzle_specifier(expr);
- if (e.errored) {
- return Failure::kErrored;
+ if (match(Token::Type::kAnd)) {
+ return check_lhs(ast::UnaryOp::kAddressOf);
}
- return e.value;
+
+ if (match(Token::Type::kStar)) {
+ return check_lhs(ast::UnaryOp::kIndirection);
+ }
+
+ return Failure::kNoMatch;
}
// variable_updating_statement
diff --git a/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc b/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc
index 6611f3e..4e1e0db 100644
--- a/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc
@@ -100,6 +100,31 @@
EXPECT_TRUE(expr->Is<ast::IdentifierExpression>());
}
+TEST_F(ParserImplTest, LHSExpression_PostfixExpression_Array) {
+ auto p = parser("*a[0]");
+ auto e = p->lhs_expression();
+ ASSERT_FALSE(p->has_error()) << p->error();
+ ASSERT_FALSE(e.errored);
+ EXPECT_TRUE(e.matched);
+ ASSERT_NE(e.value, nullptr);
+ ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
+
+ auto* u = e->As<ast::UnaryOpExpression>();
+ EXPECT_EQ(u->op, ast::UnaryOp::kIndirection);
+
+ ASSERT_TRUE(u->expr->Is<ast::IndexAccessorExpression>());
+
+ auto* access = u->expr->As<ast::IndexAccessorExpression>();
+ ASSERT_TRUE(access->object->Is<ast::IdentifierExpression>());
+
+ auto* obj = access->object->As<ast::IdentifierExpression>();
+ EXPECT_EQ(obj->symbol, p->builder().Symbols().Get("a"));
+
+ ASSERT_TRUE(access->index->Is<ast::IntLiteralExpression>());
+ auto* idx = access->index->As<ast::IntLiteralExpression>();
+ EXPECT_EQ(0, idx->value);
+}
+
TEST_F(ParserImplTest, LHSExpression_PostfixExpression) {
auto p = parser("*a.foo");
auto e = p->lhs_expression();
@@ -107,16 +132,17 @@
ASSERT_FALSE(e.errored);
EXPECT_TRUE(e.matched);
ASSERT_NE(e.value, nullptr);
- ASSERT_TRUE(e->Is<ast::MemberAccessorExpression>());
+ ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
- auto* access = e->As<ast::MemberAccessorExpression>();
- ASSERT_TRUE(access->structure->Is<ast::UnaryOpExpression>());
-
- auto* u = access->structure->As<ast::UnaryOpExpression>();
+ auto* u = e->As<ast::UnaryOpExpression>();
EXPECT_EQ(u->op, ast::UnaryOp::kIndirection);
- ASSERT_TRUE(u->expr->Is<ast::IdentifierExpression>());
- auto* struct_ident = u->expr->As<ast::IdentifierExpression>();
+ ASSERT_TRUE(u->expr->Is<ast::MemberAccessorExpression>());
+
+ auto* access = u->expr->As<ast::MemberAccessorExpression>();
+ ASSERT_TRUE(access->structure->Is<ast::IdentifierExpression>());
+
+ auto* struct_ident = access->structure->As<ast::IdentifierExpression>();
EXPECT_EQ(struct_ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(access->member->Is<ast::IdentifierExpression>());
diff --git a/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc b/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
index 8e178ab..f2adc06 100644
--- a/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
@@ -154,8 +154,6 @@
"interface",
"invariant",
"layout",
- "line",
- "lineadj",
"lowp",
"macro",
"macro_rules",
@@ -184,7 +182,6 @@
"pass",
"patch",
"pixelfragment",
- "point",
"precise",
"precision",
"premerge",
diff --git a/src/tint/resolver/address_space_layout_validation_test.cc b/src/tint/resolver/address_space_layout_validation_test.cc
index 82da573..b34b889 100644
--- a/src/tint/resolver/address_space_layout_validation_test.cc
+++ b/src/tint/resolver/address_space_layout_validation_test.cc
@@ -363,6 +363,29 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+// Make sure that this doesn't fail validation because vec3's align is 8, but
+// size is 6. 's' should be at offset 6, which is okay here.
+TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_Vec3F16MemberOffset_NoFail) {
+ // struct ScalarPackedAtEndOfVec3 {
+ // v : vec3<f16>;
+ // s : f16;
+ // };
+ // @group(0) @binding(0)
+ // var<uniform> a : ScalarPackedAtEndOfVec3;
+
+ Enable(ast::Extension::kF16);
+
+ Structure("ScalarPackedAtEndOfVec3", utils::Vector{
+ Member("v", ty.vec3(ty.f16())),
+ Member("s", ty.f16()),
+ });
+
+ GlobalVar(Source{{78, 90}}, "a", ty.type_name("ScalarPackedAtEndOfVec3"),
+ ast::AddressSpace::kUniform, Group(0_a), Binding(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
// Detect array stride must be a multiple of 16 bytes for uniform buffers
TEST_F(ResolverAddressSpaceLayoutValidationTest, UniformBuffer_InvalidArrayStride_Scalar) {
// type Inner = array<f32, 10u>;
diff --git a/src/tint/resolver/address_space_validation_test.cc b/src/tint/resolver/address_space_validation_test.cc
index 3ef19a6..60e54df 100644
--- a/src/tint/resolver/address_space_validation_test.cc
+++ b/src/tint/resolver/address_space_validation_test.cc
@@ -113,98 +113,6 @@
56:78 note: while instantiating 'var' g)");
}
-// F16 types in storage and uniform buffer is not implemented yet.
-// TODO(tint:1473, tint:1502): make these testcases valid after f16 is supported.
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferF16_TemporallyBan) {
- // var<storage> g : f16;
- Enable(ast::Extension::kF16);
-
- GlobalVar("g", ty.f16(Source{{56, 78}}), ast::AddressSpace::kStorage, Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(),
- "56:78 error: using f16 types in 'storage' address space is not "
- "implemented yet");
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferF16Alias_TemporallyBan) {
- // type a = f16;
- // var<storage, read> g : a;
- Enable(ast::Extension::kF16);
-
- auto* a = Alias("a", ty.f16());
- GlobalVar("g", ty.type_name(Source{{56, 78}}, a->name), ast::AddressSpace::kStorage,
- Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(),
- "56:78 error: using f16 types in 'storage' address space is not "
- "implemented yet");
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferVectorF16_TemporallyBan) {
- // var<storage> g : vec4<f16>;
- Enable(ast::Extension::kF16);
- GlobalVar("g", ty.vec(Source{{56, 78}}, ty.Of<f16>(), 4u), ast::AddressSpace::kStorage,
- Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(),
- "56:78 error: using f16 types in 'storage' address space is not "
- "implemented yet");
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferArrayF16_TemporallyBan) {
- // struct S { a : f16 };
- // var<storage, read> g : array<S, 3u>;
- Enable(ast::Extension::kF16);
-
- auto* s = Structure("S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}))});
- auto* a = ty.array(ty.Of(s), 3_u);
- GlobalVar("g", a, ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'storage' address "
- "space is not implemented yet"));
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructF16_TemporallyBan) {
- // struct S { x : f16 };
- // var<storage, read> g : S;
- Enable(ast::Extension::kF16);
-
- auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
- GlobalVar("g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a),
- Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' address "
- "space is not implemented yet"));
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferNoErrorStructF16Aliases_TemporallyBan) {
- // struct S { x : f16 };
- // type a1 = S;
- // var<storage, read> g : a1;
- Enable(ast::Extension::kF16);
-
- auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
- auto* a1 = Alias("a1", ty.Of(s));
- auto* a2 = Alias("a2", ty.Of(a1));
- GlobalVar("g", ty.Of(a2), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a),
- Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'storage' address "
- "space is not implemented yet"));
-}
-
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferPointer) {
// var<storage> g : ptr<private, f32>;
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
@@ -226,6 +134,27 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferF16) {
+ // var<storage> g : f16;
+ Enable(ast::Extension::kF16);
+
+ GlobalVar("g", ty.f16(Source{{56, 78}}), ast::AddressSpace::kStorage, Binding(0_a), Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferF16Alias) {
+ // type a = f16;
+ // var<storage, read> g : a;
+ Enable(ast::Extension::kF16);
+
+ auto* a = Alias("a", ty.f16());
+ GlobalVar("g", ty.type_name(Source{{56, 78}}, a->name), ast::AddressSpace::kStorage,
+ Binding(0_a), Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferVectorF32) {
// var<storage> g : vec4<f32>;
GlobalVar(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::AddressSpace::kStorage, Binding(0_a),
@@ -234,6 +163,15 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferVectorF16) {
+ // var<storage> g : vec4<f16>;
+ Enable(ast::Extension::kF16);
+ GlobalVar("g", ty.vec(Source{{56, 78}}, ty.Of<f16>(), 4u), ast::AddressSpace::kStorage,
+ Binding(0_a), Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverAddressSpaceValidationTest, StorageBufferArrayF32) {
// var<storage, read> g : array<S, 3u>;
auto* s = Structure("S", utils::Vector{Member("a", ty.f32())});
@@ -244,6 +182,68 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferArrayF16) {
+ // var<storage, read> g : array<S, 3u>;
+ Enable(ast::Extension::kF16);
+
+ auto* s = Structure("S", utils::Vector{Member("a", ty.f16())});
+ auto* a = ty.array(ty.Of(s), 3_u);
+ GlobalVar(Source{{56, 78}}, "g", a, ast::AddressSpace::kStorage, ast::Access::kRead,
+ Binding(0_a), Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructI32) {
+ // struct S { x : i32 };
+ // var<storage, read> g : S;
+ auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
+ GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
+ Binding(0_a), Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructI32Aliases) {
+ // struct S { x : i32 };
+ // type a1 = S;
+ // var<storage, read> g : a1;
+ auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
+ auto* a1 = Alias("a1", ty.Of(s));
+ auto* a2 = Alias("a2", ty.Of(a1));
+ GlobalVar(Source{{56, 78}}, "g", ty.Of(a2), ast::AddressSpace::kStorage, ast::Access::kRead,
+ Binding(0_a), Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructF16) {
+ // struct S { x : f16 };
+ // var<storage, read> g : S;
+ Enable(ast::Extension::kF16);
+
+ auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
+ GlobalVar("g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a),
+ Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructF16Aliases) {
+ // struct S { x : f16 };
+ // type a1 = S;
+ // var<storage, read> g : a1;
+ Enable(ast::Extension::kF16);
+
+ auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
+ auto* a1 = Alias("a1", ty.Of(s));
+ auto* a2 = Alias("a2", ty.Of(a1));
+ GlobalVar("g", ty.Of(a2), ast::AddressSpace::kStorage, ast::Access::kRead, Binding(0_a),
+ Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverAddressSpaceValidationTest, NotStorage_AccessMode) {
// var<private, read> g : a;
GlobalVar(Source{{56, 78}}, "g", ty.i32(), ast::AddressSpace::kPrivate, ast::Access::kRead);
@@ -282,29 +282,6 @@
R"(56:78 error: access mode 'write' is not valid for the 'storage' address space)");
}
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferStructI32) {
- // struct S { x : i32 };
- // var<storage, read> g : S;
- auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
- GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kStorage, ast::Access::kRead,
- Binding(0_a), Group(0_a));
-
- ASSERT_TRUE(r()->Resolve());
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, StorageBufferNoErrorStructI32Aliases) {
- // struct S { x : i32 };
- // type a1 = S;
- // var<storage, read> g : a1;
- auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.i32())});
- auto* a1 = Alias("a1", ty.Of(s));
- auto* a2 = Alias("a2", ty.Of(a1));
- GlobalVar(Source{{56, 78}}, "g", ty.Of(a2), ast::AddressSpace::kStorage, ast::Access::kRead,
- Binding(0_a), Group(0_a));
-
- ASSERT_TRUE(r()->Resolve());
-}
-
TEST_F(ResolverAddressSpaceValidationTest, UniformBuffer_Struct_Runtime) {
// struct S { m: array<f32>; };
// @group(0) @binding(0) var<uniform, > svar : S;
@@ -349,97 +326,6 @@
56:78 note: while instantiating 'var' g)");
}
-// F16 types in storage and uniform buffer is not implemented yet.
-// TODO(tint:1473, tint:1502): make these testcases valid after f16 is supported.
-TEST_F(ResolverAddressSpaceValidationTest, UniformBufferF16_TemporallyBan) {
- // var<uniform> g : f16;
- Enable(ast::Extension::kF16);
-
- GlobalVar("g", ty.f16(Source{{56, 78}}), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(),
- "56:78 error: using f16 types in 'uniform' address space is not "
- "implemented yet");
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, UniformBufferF16Alias_TemporallyBan) {
- // type a = f16;
- // var<uniform> g : a;
- Enable(ast::Extension::kF16);
-
- auto* a = Alias("a", ty.f16());
- GlobalVar("g", ty.type_name(Source{{56, 78}}, a->name), ast::AddressSpace::kUniform,
- Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(),
- "56:78 error: using f16 types in 'uniform' address space is not "
- "implemented yet");
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, UniformBufferVectorF16_TemporallyBan) {
- // var<uniform> g : vec4<f16>;
- Enable(ast::Extension::kF16);
- GlobalVar("g", ty.vec(Source{{56, 78}}, ty.Of<f16>(), 4u), ast::AddressSpace::kUniform,
- Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' address "
- "space is not implemented yet"));
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, UniformBufferArrayF16_TemporallyBan) {
- // struct S {
- // @size(16) f : f16;
- // }
- // var<uniform> g : array<S, 3u>;
- Enable(ast::Extension::kF16);
-
- auto* s = Structure(
- "S", utils::Vector{Member("a", ty.f16(Source{{56, 78}}), utils::Vector{MemberSize(16_a)})});
- auto* a = ty.array(ty.Of(s), 3_u);
- GlobalVar("g", a, ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_THAT(r()->error(), HasSubstr("56:78 error: using f16 types in 'uniform' address "
- "space is not implemented yet"));
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16_TemporallyBan) {
- // struct S { x : f16 };
- // var<uniform> g : S;
- Enable(ast::Extension::kF16);
-
- auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
- GlobalVar("g", ty.Of(s), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' address "
- "space is not implemented yet"));
-}
-
-TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16Aliases_TemporallyBan) {
- // struct S { x : f16 };
- // type a1 = S;
- // var<uniform> g : a1;
- Enable(ast::Extension::kF16);
-
- auto* s = Structure("S", utils::Vector{Member("x", ty.f16(Source{{12, 34}}))});
- auto* a1 = Alias("a1", ty.Of(s));
- GlobalVar("g", ty.Of(a1), ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
-
- ASSERT_FALSE(r()->Resolve());
-
- EXPECT_THAT(r()->error(), HasSubstr("12:34 error: using f16 types in 'uniform' address "
- "space is not implemented yet"));
-}
-
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferPointer) {
// var<uniform> g : ptr<private, f32>;
GlobalVar(Source{{56, 78}}, "g", ty.pointer(ty.f32(), ast::AddressSpace::kPrivate),
@@ -461,6 +347,16 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverAddressSpaceValidationTest, UniformBufferF16) {
+ // var<uniform> g : f16;
+ Enable(ast::Extension::kF16);
+
+ GlobalVar(Source{{56, 78}}, "g", ty.f16(), ast::AddressSpace::kUniform, Binding(0_a),
+ Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferVectorF32) {
// var<uniform> g : vec4<f32>;
GlobalVar(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::AddressSpace::kUniform, Binding(0_a),
@@ -469,6 +365,16 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverAddressSpaceValidationTest, UniformBufferVectorF16) {
+ // var<uniform> g : vec4<f16>;
+ Enable(ast::Extension::kF16);
+
+ GlobalVar(Source{{56, 78}}, "g", ty.vec4<f16>(), ast::AddressSpace::kUniform, Binding(0_a),
+ Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferArrayF32) {
// struct S {
// @size(16) f : f32;
@@ -481,6 +387,20 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverAddressSpaceValidationTest, UniformBufferArrayF16) {
+ // struct S {
+ // @size(16) f : f16;
+ // }
+ // var<uniform> g : array<S, 3u>;
+ Enable(ast::Extension::kF16);
+
+ auto* s = Structure("S", utils::Vector{Member("a", ty.f16(), utils::Vector{MemberSize(16_a)})});
+ auto* a = ty.array(ty.Of(s), 3_u);
+ GlobalVar(Source{{56, 78}}, "g", a, ast::AddressSpace::kUniform, Binding(0_a), Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructI32) {
// struct S { x : i32 };
// var<uniform> g : S;
@@ -503,6 +423,32 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16) {
+ // struct S { x : f16 };
+ // var<uniform> g : S;
+ Enable(ast::Extension::kF16);
+
+ auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.f16())});
+ GlobalVar(Source{{56, 78}}, "g", ty.Of(s), ast::AddressSpace::kUniform, Binding(0_a),
+ Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverAddressSpaceValidationTest, UniformBufferStructF16Aliases) {
+ // struct S { x : f16 };
+ // type a1 = S;
+ // var<uniform> g : a1;
+ Enable(ast::Extension::kF16);
+
+ auto* s = Structure("S", utils::Vector{Member(Source{{12, 34}}, "x", ty.f16())});
+ auto* a1 = Alias("a1", ty.Of(s));
+ GlobalVar(Source{{56, 78}}, "g", ty.Of(a1), ast::AddressSpace::kUniform, Binding(0_a),
+ Group(0_a));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverAddressSpaceValidationTest, PushConstantBool) {
// enable chromium_experimental_push_constant;
// var<push_constant> g : bool;
diff --git a/src/tint/resolver/builtin_test.cc b/src/tint/resolver/builtin_test.cc
index c6ca1f4..15bf5de 100644
--- a/src/tint/resolver/builtin_test.cc
+++ b/src/tint/resolver/builtin_test.cc
@@ -882,8 +882,8 @@
EXPECT_EQ(r()->error(), R"(error: no matching call to distance(vec3<f32>, vec3<f32>, vec3<f32>)
2 candidate functions:
- distance(T, T) -> T where: T is f32 or f16
- distance(vecN<T>, vecN<T>) -> T where: T is f32 or f16
+ distance(T, T) -> T where: T is abstract-float, f32 or f16
+ distance(vecN<T>, vecN<T>) -> T where: T is abstract-float, f32 or f16
)");
}
@@ -896,8 +896,8 @@
EXPECT_EQ(r()->error(), R"(error: no matching call to distance(vec3<f32>)
2 candidate functions:
- distance(T, T) -> T where: T is f32 or f16
- distance(vecN<T>, vecN<T>) -> T where: T is f32 or f16
+ distance(T, T) -> T where: T is abstract-float, f32 or f16
+ distance(vecN<T>, vecN<T>) -> T where: T is abstract-float, f32 or f16
)");
}
@@ -910,8 +910,8 @@
EXPECT_EQ(r()->error(), R"(error: no matching call to distance()
2 candidate functions:
- distance(T, T) -> T where: T is f32 or f16
- distance(vecN<T>, vecN<T>) -> T where: T is f32 or f16
+ distance(T, T) -> T where: T is abstract-float, f32 or f16
+ distance(vecN<T>, vecN<T>) -> T where: T is abstract-float, f32 or f16
)");
}
@@ -1079,54 +1079,8 @@
R"(error: no matching call to frexp(i32, ptr<workgroup, i32, read_write>)
2 candidate functions:
- frexp(T) -> __frexp_result_T where: T is f32 or f16
- frexp(vecN<T>) -> __frexp_result_vecN_T where: T is f32 or f16
-)");
-}
-
-TEST_F(ResolverBuiltinFloatTest, Frexp_Error_SecondParamFloatPtr) {
- GlobalVar("v", ty.f32(), ast::AddressSpace::kWorkgroup);
- auto* call = Call("frexp", 1_f, AddressOf("v"));
- WrapInFunction(call);
-
- EXPECT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(),
- R"(error: no matching call to frexp(f32, ptr<workgroup, f32, read_write>)
-
-2 candidate functions:
- frexp(T) -> __frexp_result_T where: T is f32 or f16
- frexp(vecN<T>) -> __frexp_result_vecN_T where: T is f32 or f16
-)");
-}
-
-TEST_F(ResolverBuiltinFloatTest, Frexp_Error_SecondParamNotAPointer) {
- auto* call = Call("frexp", 1_f, 1_i);
- WrapInFunction(call);
-
- EXPECT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(), R"(error: no matching call to frexp(f32, i32)
-
-2 candidate functions:
- frexp(T) -> __frexp_result_T where: T is f32 or f16
- frexp(vecN<T>) -> __frexp_result_vecN_T where: T is f32 or f16
-)");
-}
-
-TEST_F(ResolverBuiltinFloatTest, Frexp_Error_VectorSizesDontMatch) {
- GlobalVar("v", ty.vec4<i32>(), ast::AddressSpace::kWorkgroup);
- auto* call = Call("frexp", vec2<f32>(1_f, 2_f), AddressOf("v"));
- WrapInFunction(call);
-
- EXPECT_FALSE(r()->Resolve());
-
- EXPECT_EQ(r()->error(),
- R"(error: no matching call to frexp(vec2<f32>, ptr<workgroup, vec4<i32>, read_write>)
-
-2 candidate functions:
- frexp(T) -> __frexp_result_T where: T is f32 or f16
- frexp(vecN<T>) -> __frexp_result_vecN_T where: T is f32 or f16
+ frexp(T) -> __frexp_result_T where: T is abstract-float, f32 or f16
+ frexp(vecN<T>) -> __frexp_result_vecN_T where: T is abstract-float, f32 or f16
)");
}
@@ -1374,8 +1328,8 @@
R"(error: no matching call to modf(i32, ptr<workgroup, f32, read_write>)
2 candidate functions:
- modf(T) -> __modf_result_T where: T is f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is f32 or f16
+ modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
+ modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
)");
}
@@ -1390,8 +1344,8 @@
R"(error: no matching call to modf(f32, ptr<workgroup, i32, read_write>)
2 candidate functions:
- modf(T) -> __modf_result_T where: T is f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is f32 or f16
+ modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
+ modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
)");
}
@@ -1404,8 +1358,8 @@
EXPECT_EQ(r()->error(), R"(error: no matching call to modf(f32, f32)
2 candidate functions:
- modf(T) -> __modf_result_T where: T is f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is f32 or f16
+ modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
+ modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
)");
}
@@ -1420,8 +1374,8 @@
R"(error: no matching call to modf(vec2<f32>, ptr<workgroup, vec4<f32>, read_write>)
2 candidate functions:
- modf(T) -> __modf_result_T where: T is f32 or f16
- modf(vecN<T>) -> __modf_result_vecN_T where: T is f32 or f16
+ modf(T) -> __modf_result_T where: T is abstract-float, f32 or f16
+ modf(vecN<T>) -> __modf_result_vecN_T where: T is abstract-float, f32 or f16
)");
}
@@ -1461,7 +1415,7 @@
EXPECT_EQ(r()->error(), R"(error: no matching call to normalize()
1 candidate function:
- normalize(vecN<T>) -> vecN<T> where: T is f32 or f16
+ normalize(vecN<T>) -> vecN<T> where: T is abstract-float, f32 or f16
)");
}
@@ -1978,7 +1932,7 @@
EXPECT_EQ(r()->error(), R"(error: no matching call to determinant(mat2x3<f32>)
1 candidate function:
- determinant(matNxN<T>) -> T where: T is f32 or f16
+ determinant(matNxN<T>) -> T where: T is abstract-float, f32 or f16
)");
}
@@ -1993,7 +1947,7 @@
EXPECT_EQ(r()->error(), R"(error: no matching call to determinant(f32)
1 candidate function:
- determinant(matNxN<T>) -> T where: T is f32 or f16
+ determinant(matNxN<T>) -> T where: T is abstract-float, f32 or f16
)");
}
diff --git a/src/tint/resolver/builtins_validation_test.cc b/src/tint/resolver/builtins_validation_test.cc
index 675ff49..c0452ce 100644
--- a/src/tint/resolver/builtins_validation_test.cc
+++ b/src/tint/resolver/builtins_validation_test.cc
@@ -1099,7 +1099,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(Expr(f32(i)));
+ params.Push(Expr(f32(i + 1)));
}
auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(),
@@ -1120,7 +1120,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec2<f32>(f32(i), f32(i)));
+ params.Push(vec2<f32>(f32(i + 1), f32(i + 1)));
}
auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(),
@@ -1141,7 +1141,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec3<f32>(f32(i), f32(i), f32(i)));
+ params.Push(vec3<f32>(f32(i + 1), f32(i + 1), f32(i + 1)));
}
auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(),
@@ -1162,7 +1162,7 @@
utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) {
- params.Push(vec4<f32>(f32(i), f32(i), f32(i), f32(i)));
+ params.Push(vec4<f32>(f32(i + 1), f32(i + 1), f32(i + 1), f32(i + 1)));
}
auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(),
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index c5b51c0..159aaf4 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -202,6 +202,15 @@
return ss.str();
}
+template <typename NumberT>
+std::string OverflowExpErrorMessage(std::string_view base, NumberT value) {
+ std::stringstream ss;
+ ss << std::setprecision(20);
+ ss << base << "^" << value << " cannot be represented as "
+ << "'" << FriendlyName<NumberT>() << "'";
+ return ss.str();
+}
+
/// @returns the number of consecutive leading bits in `@p e` set to `@p bit_value_to_count`.
template <typename T>
std::make_unsigned_t<T> CountLeadingBits(T e, T bit_value_to_count) {
@@ -403,13 +412,26 @@
const sem::Type* target_ty,
const Source& source) const override {
// Convert each of the composite element types.
- auto* el_ty = sem::Type::ElementOf(target_ty);
utils::Vector<const sem::Constant*, 4> conv_els;
conv_els.Reserve(elements.Length());
+ std::function<const sem::Type*(size_t idx)> target_el_ty;
+ if (auto* str = target_ty->As<sem::Struct>()) {
+ if (str->Members().size() != elements.Length()) {
+ TINT_ICE(Resolver, builder.Diagnostics())
+ << "const-eval conversion of structure has mismatched element counts";
+ return utils::Failure;
+ }
+ target_el_ty = [str](size_t idx) { return str->Members()[idx]->Type(); };
+ } else {
+ auto* el_ty = sem::Type::ElementOf(target_ty);
+ target_el_ty = [el_ty](size_t) { return el_ty; };
+ }
+
for (auto* el : elements) {
- // Note: This file is the only place where `sem::Constant`s are created, so this
+ // Note: This file is the only place where `sem::Constant`s are created, so the
// static_cast is safe.
- auto conv_el = static_cast<const ImplConstant*>(el)->Convert(builder, el_ty, source);
+ auto conv_el = static_cast<const ImplConstant*>(el)->Convert(
+ builder, target_el_ty(conv_els.Length()), source);
if (!conv_el) {
return utils::Failure;
}
@@ -439,6 +461,8 @@
/// CreateElement constructs and returns an Element<T>.
template <typename T>
ImplResult CreateElement(ProgramBuilder& builder, const Source& source, const sem::Type* t, T v) {
+ TINT_ASSERT(Resolver, t->is_scalar());
+
if constexpr (IsFloatingPoint<T>) {
if (!std::isfinite(v.value)) {
auto msg = OverflowErrorMessage(v, builder.FriendlyName(t));
@@ -630,8 +654,9 @@
F&& f,
const sem::Constant* c0,
const sem::Constant* c1) {
- uint32_t n0 = 0, n1 = 0;
+ uint32_t n0 = 0;
sem::Type::ElementOf(c0->Type(), &n0);
+ uint32_t n1 = 0;
sem::Type::ElementOf(c1->Type(), &n1);
uint32_t max_n = std::max(n0, n1);
// If arity of both constants is 1, invoke callback
@@ -642,7 +667,7 @@
utils::Vector<const sem::Constant*, 8> els;
els.Reserve(max_n);
for (uint32_t i = 0; i < max_n; i++) {
- auto nested_or_self = [&](auto& c, uint32_t num_elems) {
+ auto nested_or_self = [&](auto* c, uint32_t num_elems) {
if (num_elems == 1) {
return c;
}
@@ -871,15 +896,22 @@
template <typename NumberT>
utils::Result<NumberT> ConstEval::Det2(const Source& source,
- NumberT a1,
- NumberT a2,
- NumberT b1,
- NumberT b2) {
- auto r1 = Mul(source, a1, b2);
+ NumberT a,
+ NumberT b,
+ NumberT c,
+ NumberT d) {
+ // | a c |
+ // | b d |
+ //
+ // =
+ //
+ // a * d - c * b
+
+ auto r1 = Mul(source, a, d);
if (!r1) {
return utils::Failure;
}
- auto r2 = Mul(source, b1, a2);
+ auto r2 = Mul(source, c, b);
if (!r2) {
return utils::Failure;
}
@@ -891,6 +923,129 @@
}
template <typename NumberT>
+utils::Result<NumberT> ConstEval::Det3(const Source& source,
+ NumberT a,
+ NumberT b,
+ NumberT c,
+ NumberT d,
+ NumberT e,
+ NumberT f,
+ NumberT g,
+ NumberT h,
+ NumberT i) {
+ // | a d g |
+ // | b e h |
+ // | c f i |
+ //
+ // =
+ //
+ // a | e h | - d | b h | + g | b e |
+ // | f i | | c i | | c f |
+
+ auto det1 = Det2(source, e, f, h, i);
+ if (!det1) {
+ return utils::Failure;
+ }
+ auto a_det1 = Mul(source, a, det1.Get());
+ if (!a_det1) {
+ return utils::Failure;
+ }
+ auto det2 = Det2(source, b, c, h, i);
+ if (!det2) {
+ return utils::Failure;
+ }
+ auto d_det2 = Mul(source, d, det2.Get());
+ if (!d_det2) {
+ return utils::Failure;
+ }
+ auto det3 = Det2(source, b, c, e, f);
+ if (!det3) {
+ return utils::Failure;
+ }
+ auto g_det3 = Mul(source, g, det3.Get());
+ if (!g_det3) {
+ return utils::Failure;
+ }
+ auto r = Sub(source, a_det1.Get(), d_det2.Get());
+ if (!r) {
+ return utils::Failure;
+ }
+ return Add(source, r.Get(), g_det3.Get());
+}
+
+template <typename NumberT>
+utils::Result<NumberT> ConstEval::Det4(const Source& source,
+ NumberT a,
+ NumberT b,
+ NumberT c,
+ NumberT d,
+ NumberT e,
+ NumberT f,
+ NumberT g,
+ NumberT h,
+ NumberT i,
+ NumberT j,
+ NumberT k,
+ NumberT l,
+ NumberT m,
+ NumberT n,
+ NumberT o,
+ NumberT p) {
+ // | a e i m |
+ // | b f j n |
+ // | c g k o |
+ // | d h l p |
+ //
+ // =
+ //
+ // a | f j n | - e | b j n | + i | b f n | - m | b f j |
+ // | g k o | | c k o | | c g o | | c g k |
+ // | h l p | | d l p | | d h p | | d h l |
+
+ auto det1 = Det3(source, f, g, h, j, k, l, n, o, p);
+ if (!det1) {
+ return utils::Failure;
+ }
+ auto a_det1 = Mul(source, a, det1.Get());
+ if (!a_det1) {
+ return utils::Failure;
+ }
+ auto det2 = Det3(source, b, c, d, j, k, l, n, o, p);
+ if (!det2) {
+ return utils::Failure;
+ }
+ auto e_det2 = Mul(source, e, det2.Get());
+ if (!e_det2) {
+ return utils::Failure;
+ }
+ auto det3 = Det3(source, b, c, d, f, g, h, n, o, p);
+ if (!det3) {
+ return utils::Failure;
+ }
+ auto i_det3 = Mul(source, i, det3.Get());
+ if (!i_det3) {
+ return utils::Failure;
+ }
+ auto det4 = Det3(source, b, c, d, f, g, h, j, k, l);
+ if (!det4) {
+ return utils::Failure;
+ }
+ auto m_det4 = Mul(source, m, det4.Get());
+ if (!m_det4) {
+ return utils::Failure;
+ }
+ auto r = Sub(source, a_det1.Get(), e_det2.Get());
+ if (!r) {
+ return utils::Failure;
+ }
+ r = Add(source, r.Get(), i_det3.Get());
+ if (!r) {
+ return utils::Failure;
+ }
+ return Sub(source, r.Get(), m_det4.Get());
+}
+
+template <typename NumberT>
utils::Result<NumberT> ConstEval::Sqrt(const Source& source, NumberT v) {
if (v < NumberT(0)) {
AddError("sqrt must be called with a value >= 0", source);
@@ -1013,6 +1168,27 @@
return utils::Failure;
}
+ConstEval::Result ConstEval::Length(const Source& source,
+ const sem::Type* ty,
+ const sem::Constant* c0) {
+ auto* vec_ty = c0->Type()->As<sem::Vector>();
+ // Evaluates to the absolute value of e if T is scalar.
+ if (vec_ty == nullptr) {
+ auto create = [&](auto e) {
+ using NumberT = decltype(e);
+ return CreateElement(builder, source, ty, NumberT{std::abs(e)});
+ };
+ return Dispatch_fa_f32_f16(create, c0);
+ }
+
+ // Evaluates to sqrt(e[0]^2 + e[1]^2 + ...) if T is a vector type.
+ auto d = Dot(source, c0, c0);
+ if (!d) {
+ return utils::Failure;
+ }
+ return Dispatch_fa_f32_f16(SqrtFunc(source, ty), d.Get());
+}
+
auto ConstEval::Det2Func(const Source& source, const sem::Type* elem_ty) {
return [=](auto a, auto b, auto c, auto d) -> ImplResult {
if (auto r = Det2(source, a, b, c, d)) {
@@ -1022,6 +1198,26 @@
};
}
+auto ConstEval::Det3Func(const Source& source, const sem::Type* elem_ty) {
+ return
+ [=](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h, auto i) -> ImplResult {
+ if (auto r = Det3(source, a, b, c, d, e, f, g, h, i)) {
+ return CreateElement(builder, source, elem_ty, r.Get());
+ }
+ return utils::Failure;
+ };
+}
+
+auto ConstEval::Det4Func(const Source& source, const sem::Type* elem_ty) {
+ return [=](auto a, auto b, auto c, auto d, auto e, auto f, auto g, auto h, auto i, auto j,
+ auto k, auto l, auto m, auto n, auto o, auto p) -> ImplResult {
+ if (auto r = Det4(source, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)) {
+ return CreateElement(builder, source, elem_ty, r.Get());
+ }
+ return utils::Failure;
+ };
+}
+
ConstEval::Result ConstEval::Literal(const sem::Type* ty, const ast::LiteralExpression* literal) {
auto& source = literal->source;
return Switch(
@@ -2014,6 +2210,62 @@
return TransformElements(builder, ty, transform, args[0]);
}
+ConstEval::Result ConstEval::determinant(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto calculate = [&]() -> ImplResult {
+ auto* m = args[0];
+ auto* mat_ty = m->Type()->As<sem::Matrix>();
+ auto me = [&](size_t r, size_t c) { return m->Index(c)->Index(r); };
+ switch (mat_ty->rows()) {
+ case 2:
+ return Dispatch_fa_f32_f16(Det2Func(source, ty), //
+ me(0, 0), me(1, 0), //
+ me(0, 1), me(1, 1));
+
+ case 3:
+ return Dispatch_fa_f32_f16(Det3Func(source, ty), //
+ me(0, 0), me(1, 0), me(2, 0), //
+ me(0, 1), me(1, 1), me(2, 1), //
+ me(0, 2), me(1, 2), me(2, 2));
+
+ case 4:
+ return Dispatch_fa_f32_f16(Det4Func(source, ty), //
+ me(0, 0), me(1, 0), me(2, 0), me(3, 0), //
+ me(0, 1), me(1, 1), me(2, 1), me(3, 1), //
+ me(0, 2), me(1, 2), me(2, 2), me(3, 2), //
+ me(0, 3), me(1, 3), me(2, 3), me(3, 3));
+ }
+ TINT_ICE(Resolver, builder.Diagnostics()) << "Unexpected number of matrix rows";
+ return utils::Failure;
+ };
+ auto r = calculate();
+ if (!r) {
+ AddNote("when calculating determinant", source);
+ }
+ return r;
+}
+
+ConstEval::Result ConstEval::distance(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto err = [&]() -> ImplResult {
+ AddNote("when calculating distance", source);
+ return utils::Failure;
+ };
+
+ auto minus = OpMinus(args[0]->Type(), args, source);
+ if (!minus) {
+ return err();
+ }
+
+ auto len = Length(source, ty, minus.Get());
+ if (!len) {
+ return err();
+ }
+ return len;
+}
+
ConstEval::Result ConstEval::dot(const sem::Type*,
utils::VectorRef<const sem::Constant*> args,
const Source& source) {
@@ -2024,6 +2276,42 @@
return r;
}
+ConstEval::Result ConstEval::exp(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto transform = [&](const sem::Constant* c0) {
+ auto create = [&](auto e0) -> ImplResult {
+ using NumberT = decltype(e0);
+ auto val = NumberT(std::exp(e0));
+ if (!std::isfinite(val.value)) {
+ AddError(OverflowExpErrorMessage("e", e0), source);
+ return utils::Failure;
+ }
+ return CreateElement(builder, source, c0->Type(), val);
+ };
+ return Dispatch_fa_f32_f16(create, c0);
+ };
+ return TransformElements(builder, ty, transform, args[0]);
+}
+
+ConstEval::Result ConstEval::exp2(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto transform = [&](const sem::Constant* c0) {
+ auto create = [&](auto e0) -> ImplResult {
+ using NumberT = decltype(e0);
+ auto val = NumberT(std::exp2(e0));
+ if (!std::isfinite(val.value)) {
+ AddError(OverflowExpErrorMessage("2", e0), source);
+ return utils::Failure;
+ }
+ return CreateElement(builder, source, c0->Type(), val);
+ };
+ return Dispatch_fa_f32_f16(create, c0);
+ };
+ return TransformElements(builder, ty, transform, args[0]);
+}
+
ConstEval::Result ConstEval::extractBits(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source& source) {
@@ -2161,6 +2449,106 @@
return TransformElements(builder, ty, transform, args[0]);
}
+ConstEval::Result ConstEval::fma(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto transform = [&](const sem::Constant* c1, const sem::Constant* c2,
+ const sem::Constant* c3) {
+ auto create = [&](auto e1, auto e2, auto e3) -> ImplResult {
+ auto err_msg = [&] {
+ AddNote("when calculating fma", source);
+ return utils::Failure;
+ };
+
+ auto mul = Mul(source, e1, e2);
+ if (!mul) {
+ return err_msg();
+ }
+
+ auto val = Add(source, mul.Get(), e3);
+ if (!val) {
+ return err_msg();
+ }
+ return CreateElement(builder, source, c1->Type(), val.Get());
+ };
+ return Dispatch_fa_f32_f16(create, c1, c2, c3);
+ };
+ return TransformElements(builder, ty, transform, args[0], args[1], args[2]);
+}
+
+ConstEval::Result ConstEval::frexp(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto* arg = args[0];
+
+ struct FractExp {
+ ImplResult fract;
+ ImplResult exp;
+ };
+
+ auto scalar = [&](const sem::Constant* s) {
+ int exp = 0;
+ double fract = std::frexp(s->As<AFloat>(), &exp);
+ return Switch(
+ s->Type(),
+ [&](const sem::F32*) {
+ return FractExp{
+ CreateElement(builder, source, builder.create<sem::F32>(), f32(fract)),
+ CreateElement(builder, source, builder.create<sem::I32>(), i32(exp)),
+ };
+ },
+ [&](const sem::F16*) {
+ return FractExp{
+ CreateElement(builder, source, builder.create<sem::F16>(), f16(fract)),
+ CreateElement(builder, source, builder.create<sem::I32>(), i32(exp)),
+ };
+ },
+ [&](const sem::AbstractFloat*) {
+ return FractExp{
+ CreateElement(builder, source, builder.create<sem::AbstractFloat>(),
+ AFloat(fract)),
+ CreateElement(builder, source, builder.create<sem::AbstractInt>(), AInt(exp)),
+ };
+ },
+ [&](Default) {
+ TINT_ICE(Resolver, builder.Diagnostics())
+ << "unhandled element type for frexp() const-eval: "
+ << builder.FriendlyName(s->Type());
+ return FractExp{utils::Failure, utils::Failure};
+ });
+ };
+
+ if (auto* vec = arg->Type()->As<sem::Vector>()) {
+ utils::Vector<const sem::Constant*, 4> fract_els;
+ utils::Vector<const sem::Constant*, 4> exp_els;
+ for (uint32_t i = 0; i < vec->Width(); i++) {
+ auto fe = scalar(arg->Index(i));
+ if (!fe.fract || !fe.exp) {
+ return utils::Failure;
+ }
+ fract_els.Push(fe.fract.Get());
+ exp_els.Push(fe.exp.Get());
+ }
+ auto fract_ty = builder.create<sem::Vector>(fract_els[0]->Type(), vec->Width());
+ auto exp_ty = builder.create<sem::Vector>(exp_els[0]->Type(), vec->Width());
+ return CreateComposite(builder, ty,
+ utils::Vector<const sem::Constant*, 2>{
+ CreateComposite(builder, fract_ty, std::move(fract_els)),
+ CreateComposite(builder, exp_ty, std::move(exp_els)),
+ });
+ } else {
+ auto fe = scalar(arg);
+ if (!fe.fract || !fe.exp) {
+ return utils::Failure;
+ }
+ return CreateComposite(builder, ty,
+ utils::Vector<const sem::Constant*, 2>{
+ fe.fract.Get(),
+ fe.exp.Get(),
+ });
+ }
+}
+
ConstEval::Result ConstEval::insertBits(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source& source) {
@@ -2213,35 +2601,84 @@
return TransformElements(builder, ty, transform, args[0], args[1]);
}
+ConstEval::Result ConstEval::inverseSqrt(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto transform = [&](const sem::Constant* c0) {
+ auto create = [&](auto e) -> ImplResult {
+ using NumberT = decltype(e);
+
+ if (e <= NumberT(0)) {
+ AddError("inverseSqrt must be called with a value > 0", source);
+ return utils::Failure;
+ }
+
+ auto err = [&] {
+ AddNote("when calculating inverseSqrt", source);
+ return utils::Failure;
+ };
+
+ auto s = Sqrt(source, e);
+ if (!s) {
+ return err();
+ }
+ auto div = Div(source, NumberT(1), s.Get());
+ if (!div) {
+ return err();
+ }
+
+ return CreateElement(builder, source, c0->Type(), div.Get());
+ };
+ return Dispatch_fa_f32_f16(create, c0);
+ };
+
+ return TransformElements(builder, ty, transform, args[0]);
+}
+
ConstEval::Result ConstEval::length(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source& source) {
- auto calculate = [&]() -> ImplResult {
- auto* vec_ty = args[0]->Type()->As<sem::Vector>();
-
- // Evaluates to the absolute value of e if T is scalar.
- if (vec_ty == nullptr) {
- auto create = [&](auto e) {
- using NumberT = decltype(e);
- return CreateElement(builder, source, ty, NumberT{std::abs(e)});
- };
- return Dispatch_fa_f32_f16(create, args[0]);
- }
-
- // Evaluates to sqrt(e[0]^2 + e[1]^2 + ...) if T is a vector type.
- auto d = Dot(source, args[0], args[0]);
- if (!d) {
- return utils::Failure;
- }
- return Dispatch_fa_f32_f16(SqrtFunc(source, ty), d.Get());
- };
- auto r = calculate();
+ auto r = Length(source, ty, args[0]);
if (!r) {
AddNote("when calculating length", source);
}
return r;
}
+ConstEval::Result ConstEval::log(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto transform = [&](const sem::Constant* c0) {
+ auto create = [&](auto v) -> ImplResult {
+ using NumberT = decltype(v);
+ if (v <= NumberT(0)) {
+ AddError("log must be called with a value > 0", source);
+ return utils::Failure;
+ }
+ return CreateElement(builder, source, c0->Type(), NumberT(std::log(v)));
+ };
+ return Dispatch_fa_f32_f16(create, c0);
+ };
+ return TransformElements(builder, ty, transform, args[0]);
+}
+
+ConstEval::Result ConstEval::log2(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto transform = [&](const sem::Constant* c0) {
+ auto create = [&](auto v) -> ImplResult {
+ using NumberT = decltype(v);
+ if (v <= NumberT(0)) {
+ AddError("log2 must be called with a value > 0", source);
+ return utils::Failure;
+ }
+ return CreateElement(builder, source, c0->Type(), NumberT(std::log2(v)));
+ };
+ return Dispatch_fa_f32_f16(create, c0);
+ };
+ return TransformElements(builder, ty, transform, args[0]);
+}
+
ConstEval::Result ConstEval::max(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source& source) {
@@ -2300,6 +2737,23 @@
return CreateComposite(builder, ty, std::move(fields));
}
+ConstEval::Result ConstEval::normalize(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source) {
+ auto* len_ty = sem::Type::DeepestElementOf(ty);
+ auto len = Length(source, len_ty, args[0]);
+ if (!len) {
+ AddNote("when calculating normalize", source);
+ return utils::Failure;
+ }
+ auto* v = len.Get();
+ if (v->AllZero()) {
+ AddError("zero length vector can not be normalized", source);
+ return utils::Failure;
+ }
+ return OpDivide(ty, utils::Vector{args[0], v}, source);
+}
+
ConstEval::Result ConstEval::pack2x16float(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source& source) {
@@ -2681,6 +3135,26 @@
return TransformElements(builder, ty, transform, args[0]);
}
+ConstEval::Result ConstEval::transpose(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source&) {
+ auto* m = args[0];
+ auto* mat_ty = m->Type()->As<sem::Matrix>();
+ auto me = [&](size_t r, size_t c) { return m->Index(c)->Index(r); };
+ auto* result_mat_ty = ty->As<sem::Matrix>();
+
+ // Produce column vectors from each row
+ utils::Vector<const sem::Constant*, 4> result_mat;
+ for (size_t r = 0; r < mat_ty->rows(); ++r) {
+ utils::Vector<const sem::Constant*, 4> new_col_vec;
+ for (size_t c = 0; c < mat_ty->columns(); ++c) {
+ new_col_vec.Push(me(r, c));
+ }
+ result_mat.Push(CreateComposite(builder, result_mat_ty->ColumnType(), new_col_vec));
+ }
+ return CreateComposite(builder, ty, result_mat);
+}
+
ConstEval::Result ConstEval::trunc(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source& source) {
diff --git a/src/tint/resolver/const_eval.h b/src/tint/resolver/const_eval.h
index f290adb..0c8ec6b 100644
--- a/src/tint/resolver/const_eval.h
+++ b/src/tint/resolver/const_eval.h
@@ -539,6 +539,7 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// degrees builtin
/// @param ty the expression type
/// @param args the input arguments
/// @param source the source location of the conversion
@@ -547,6 +548,24 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// determinant builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location of the conversion
+ /// @return the result value, or null if the value cannot be calculated
+ Result determinant(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
+ /// distance builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location of the conversion
+ /// @return the result value, or null if the value cannot be calculated
+ Result distance(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
/// dot builtin
/// @param ty the expression type
/// @param args the input arguments
@@ -556,6 +575,24 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// exp builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result exp(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
+ /// exp2 builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result exp2(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
/// extractBits builtin
/// @param ty the expression type
/// @param args the input arguments
@@ -592,6 +629,24 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// fma builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result fma(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
+ /// frexp builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result frexp(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
/// insertBits builtin
/// @param ty the expression type
/// @param args the input arguments
@@ -601,6 +656,15 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// inverseSqrt builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result inverseSqrt(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
/// length builtin
/// @param ty the expression type
/// @param args the input arguments
@@ -610,6 +674,24 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// log builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result log(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
+ /// log2 builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result log2(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
/// max builtin
/// @param ty the expression type
/// @param args the input arguments
@@ -637,6 +719,15 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// normalize builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result normalize(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
/// pack2x16float builtin
/// @param ty the expression type
/// @param args the input arguments
@@ -808,6 +899,15 @@
utils::VectorRef<const sem::Constant*> args,
const Source& source);
+ /// transpose builtin
+ /// @param ty the expression type
+ /// @param args the input arguments
+ /// @param source the source location
+ /// @return the result value, or null if the value cannot be calculated
+ Result transpose(const sem::Type* ty,
+ utils::VectorRef<const sem::Constant*> args,
+ const Source& source);
+
/// trunc builtin
/// @param ty the expression type
/// @param args the input arguments
@@ -967,18 +1067,87 @@
NumberT b3,
NumberT b4);
- /// Returns the determinant of the 2x2 matrix [(a1, a2), (b1, b2)]
+ /// Returns the determinant of the 2x2 matrix:
+ /// | a c |
+ /// | b d |
/// @param source the source location
- /// @param a1 component 1 of the first column vector
- /// @param a2 component 2 of the first column vector
- /// @param b1 component 1 of the second column vector
- /// @param b2 component 2 of the second column vector
+ /// @param a component 1 of the first column vector
+ /// @param b component 2 of the first column vector
+ /// @param c component 1 of the second column vector
+ /// @param d component 2 of the second column vector
template <typename NumberT>
- utils::Result<NumberT> Det2(const Source& source,
- NumberT a1,
- NumberT a2,
- NumberT b1,
- NumberT b2);
+ utils::Result<NumberT> Det2(const Source& source, //
+ NumberT a,
+ NumberT b,
+ NumberT c,
+ NumberT d);
+
+ /// Returns the determinant of the 3x3 matrix:
+ /// | a d g |
+ /// | b e h |
+ /// | c f i |
+ /// @param source the source location
+ /// @param a component 1 of the first column vector
+ /// @param b component 2 of the first column vector
+ /// @param c component 3 of the first column vector
+ /// @param d component 1 of the second column vector
+ /// @param e component 2 of the second column vector
+ /// @param f component 3 of the second column vector
+ /// @param g component 1 of the third column vector
+ /// @param h component 2 of the third column vector
+ /// @param i component 3 of the third column vector
+ template <typename NumberT>
+ utils::Result<NumberT> Det3(const Source& source,
+ NumberT a,
+ NumberT b,
+ NumberT c,
+ NumberT d,
+ NumberT e,
+ NumberT f,
+ NumberT g,
+ NumberT h,
+ NumberT i);
+
+ /// Returns the determinant of the 4x4 matrix:
+ /// | a e i m |
+ /// | b f j n |
+ /// | c g k o |
+ /// | d h l p |
+ /// @param source the source location
+ /// @param a component 1 of the first column vector
+ /// @param b component 2 of the first column vector
+ /// @param c component 3 of the first column vector
+ /// @param d component 4 of the first column vector
+ /// @param e component 1 of the second column vector
+ /// @param f component 2 of the second column vector
+ /// @param g component 3 of the second column vector
+ /// @param h component 4 of the second column vector
+ /// @param i component 1 of the third column vector
+ /// @param j component 2 of the third column vector
+ /// @param k component 3 of the third column vector
+ /// @param l component 4 of the third column vector
+ /// @param m component 1 of the fourth column vector
+ /// @param n component 2 of the fourth column vector
+ /// @param o component 3 of the fourth column vector
+ /// @param p component 4 of the fourth column vector
+ template <typename NumberT>
+ utils::Result<NumberT> Det4(const Source& source,
+ NumberT a,
+ NumberT b,
+ NumberT c,
+ NumberT d,
+ NumberT e,
+ NumberT f,
+ NumberT g,
+ NumberT h,
+ NumberT i,
+ NumberT j,
+ NumberT k,
+ NumberT l,
+ NumberT m,
+ NumberT n,
+ NumberT o,
+ NumberT p);
template <typename NumberT>
utils::Result<NumberT> Sqrt(const Source& source, NumberT v);
@@ -1048,6 +1217,20 @@
/// @returns the callable function
auto Det2Func(const Source& source, const sem::Type* elem_ty);
+ /// Returns a callable that calls Det3, and creates a Constant with its result of type `elem_ty`
+ /// if successful, or returns Failure otherwise.
+ /// @param source the source location
+ /// @param elem_ty the element type of the Constant to create on success
+ /// @returns the callable function
+ auto Det3Func(const Source& source, const sem::Type* elem_ty);
+
+ /// Returns a callable that calls Det4, and creates a Constant with its result of type `elem_ty`
+ /// if successful, or returns Failure otherwise.
+ /// @param source the source location
+ /// @param elem_ty the element type of the Constant to create on success
+ /// @returns the callable function
+ auto Det4Func(const Source& source, const sem::Type* elem_ty);
+
/// Returns a callable that calls Clamp, and creates a Constant with its result of type
/// `elem_ty` if successful, or returns Failure otherwise.
/// @param source the source location
@@ -1069,6 +1252,13 @@
/// @returns the dot product
Result Dot(const Source& source, const sem::Constant* v1, const sem::Constant* v2);
+ /// Return sthe length of c0
+ /// @param source the source location
+ /// @param ty the return type
+ /// @param c0 the constant to calculate the length of
+ /// @returns the length of c0
+ Result Length(const Source& source, const sem::Type* ty, const sem::Constant* c0);
+
ProgramBuilder& builder;
};
diff --git a/src/tint/resolver/const_eval_binary_op_test.cc b/src/tint/resolver/const_eval_binary_op_test.cc
index 70176c7..a35214a 100644
--- a/src/tint/resolver/const_eval_binary_op_test.cc
+++ b/src/tint/resolver/const_eval_binary_op_test.cc
@@ -22,30 +22,26 @@
namespace tint::resolver {
namespace {
-// Bring in std::ostream& operator<<(std::ostream& o, const Types& types)
-using resolver::operator<<;
-
struct Case {
struct Success {
- Types value;
+ Value value;
};
struct Failure {
std::string error;
};
- Types lhs;
- Types rhs;
+ Value lhs;
+ Value rhs;
utils::Result<Success, Failure> expected;
};
struct ErrorCase {
- Types lhs;
- Types rhs;
+ Value lhs;
+ Value rhs;
};
/// Creates a Case with Values of any type
-template <typename T, typename U, typename V>
-Case C(Value<T> lhs, Value<U> rhs, Value<V> expected) {
+Case C(Value lhs, Value rhs, Value expected) {
return Case{std::move(lhs), std::move(rhs), Case::Success{std::move(expected)}};
}
@@ -56,8 +52,7 @@
}
/// Creates an failure Case with Values of any type
-template <typename T, typename U>
-Case E(Value<T> lhs, Value<U> rhs, std::string error) {
+Case E(Value lhs, Value rhs, std::string error) {
return Case{std::move(lhs), std::move(rhs), Case::Failure{std::move(error)}};
}
@@ -71,7 +66,7 @@
static std::ostream& operator<<(std::ostream& o, const Case& c) {
o << "lhs: " << c.lhs << ", rhs: " << c.rhs << ", expected: ";
if (c.expected) {
- auto s = c.expected.Get();
+ auto& s = c.expected.Get();
o << s.value;
} else {
o << "[ERROR: " << c.expected.Failure().error << "]";
@@ -91,15 +86,16 @@
auto op = std::get<0>(GetParam());
auto& c = std::get<1>(GetParam());
- auto* lhs_expr = ToValueBase(c.lhs)->Expr(*this);
- auto* rhs_expr = ToValueBase(c.rhs)->Expr(*this);
+ auto* lhs_expr = c.lhs.Expr(*this);
+ auto* rhs_expr = c.rhs.Expr(*this);
+
auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, op, lhs_expr, rhs_expr);
GlobalConst("C", expr);
if (c.expected) {
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto expected_case = c.expected.Get();
- auto* expected = ToValueBase(expected_case.value);
+ auto& expected = expected_case.value;
auto* sem = Sem().Get(expr);
const sem::Constant* value = sem->ConstantValue();
@@ -707,7 +703,6 @@
OpOrIntCases<u32>()))));
TEST_F(ResolverConstEvalTest, NotAndOrOfVecs) {
- // const C = !((vec2(true, true) & vec2(true, false)) | vec2(false, true));
auto v1 = Vec(true, true).Expr(*this);
auto v2 = Vec(true, false).Expr(*this);
auto v3 = Vec(false, true).Expr(*this);
@@ -978,8 +973,8 @@
// i32/u32 left shift by >= 32 -> error
using ResolverConstEvalShiftLeftConcreteGeqBitWidthError = ResolverTestWithParam<ErrorCase>;
TEST_P(ResolverConstEvalShiftLeftConcreteGeqBitWidthError, Test) {
- auto* lhs_expr = ToValueBase(GetParam().lhs)->Expr(*this);
- auto* rhs_expr = ToValueBase(GetParam().rhs)->Expr(*this);
+ auto* lhs_expr = GetParam().lhs.Expr(*this);
+ auto* rhs_expr = GetParam().rhs.Expr(*this);
GlobalConst("c", Shl(Source{{1, 1}}, lhs_expr, rhs_expr));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
@@ -1024,8 +1019,8 @@
// AInt left shift results in sign change error
using ResolverConstEvalShiftLeftSignChangeError = ResolverTestWithParam<ErrorCase>;
TEST_P(ResolverConstEvalShiftLeftSignChangeError, Test) {
- auto* lhs_expr = ToValueBase(GetParam().lhs)->Expr(*this);
- auto* rhs_expr = ToValueBase(GetParam().rhs)->Expr(*this);
+ auto* lhs_expr = GetParam().lhs.Expr(*this);
+ auto* rhs_expr = GetParam().rhs.Expr(*this);
GlobalConst("c", Shl(Source{{1, 1}}, lhs_expr, rhs_expr));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "1:1 error: shift left operation results in sign change");
diff --git a/src/tint/resolver/const_eval_builtin_test.cc b/src/tint/resolver/const_eval_builtin_test.cc
index eccd711..dabe7d9 100644
--- a/src/tint/resolver/const_eval_builtin_test.cc
+++ b/src/tint/resolver/const_eval_builtin_test.cc
@@ -22,15 +22,12 @@
namespace tint::resolver {
namespace {
-// Bring in std::ostream& operator<<(std::ostream& o, const Types& types)
-using resolver::operator<<;
-
struct Case {
- Case(utils::VectorRef<Types> in_args, utils::VectorRef<Types> expected_values)
+ Case(utils::VectorRef<Value> in_args, utils::VectorRef<Value> expected_values)
: args(std::move(in_args)),
expected(Success{std::move(expected_values), CheckConstantFlags{}}) {}
- Case(utils::VectorRef<Types> in_args, std::string expected_err)
+ Case(utils::VectorRef<Value> in_args, std::string expected_err)
: args(std::move(in_args)), expected(Failure{std::move(expected_err)}) {}
/// Expected value may be positive or negative
@@ -52,14 +49,14 @@
}
struct Success {
- utils::Vector<Types, 2> values;
+ utils::Vector<Value, 2> values;
CheckConstantFlags flags;
};
struct Failure {
std::string error;
};
- utils::Vector<Types, 8> args;
+ utils::Vector<Value, 8> args;
utils::Result<Success, Failure> expected;
};
@@ -94,34 +91,34 @@
using ScalarTypes = std::variant<AInt, AFloat, u32, i32, f32, f16>;
/// Creates a Case with Values for args and result
-static Case C(std::initializer_list<Types> args, Types result) {
- return Case{utils::Vector<Types, 8>{args}, utils::Vector<Types, 2>{std::move(result)}};
+static Case C(std::initializer_list<Value> args, Value result) {
+ return Case{utils::Vector<Value, 8>{args}, utils::Vector<Value, 2>{std::move(result)}};
}
/// Creates a Case with Values for args and result
-static Case C(std::initializer_list<Types> args, std::initializer_list<Types> results) {
- return Case{utils::Vector<Types, 8>{args}, utils::Vector<Types, 2>{results}};
+static Case C(std::initializer_list<Value> args, std::initializer_list<Value> results) {
+ return Case{utils::Vector<Value, 8>{args}, utils::Vector<Value, 2>{results}};
}
/// Convenience overload that creates a Case with just scalars
static Case C(std::initializer_list<ScalarTypes> sargs, ScalarTypes sresult) {
- utils::Vector<Types, 8> args;
+ utils::Vector<Value, 8> args;
for (auto& sa : sargs) {
std::visit([&](auto&& v) { return args.Push(Val(v)); }, sa);
}
- Types result = Val(0_a);
+ Value result = Val(0_a);
std::visit([&](auto&& v) { result = Val(v); }, sresult);
- return Case{std::move(args), utils::Vector<Types, 2>{std::move(result)}};
+ return Case{std::move(args), utils::Vector<Value, 2>{std::move(result)}};
}
/// Creates a Case with Values for args and result
static Case C(std::initializer_list<ScalarTypes> sargs,
std::initializer_list<ScalarTypes> sresults) {
- utils::Vector<Types, 8> args;
+ utils::Vector<Value, 8> args;
for (auto& sa : sargs) {
std::visit([&](auto&& v) { return args.Push(Val(v)); }, sa);
}
- utils::Vector<Types, 2> results;
+ utils::Vector<Value, 2> results;
for (auto& sa : sresults) {
std::visit([&](auto&& v) { return results.Push(Val(v)); }, sa);
}
@@ -129,13 +126,13 @@
}
/// Creates a Case with Values for args and expected error
-static Case E(std::initializer_list<Types> args, std::string err) {
- return Case{utils::Vector<Types, 8>{args}, std::move(err)};
+static Case E(std::initializer_list<Value> args, std::string err) {
+ return Case{utils::Vector<Value, 8>{args}, std::move(err)};
}
/// Convenience overload that creates an expected-error Case with just scalars
static Case E(std::initializer_list<ScalarTypes> sargs, std::string err) {
- utils::Vector<Types, 8> args;
+ utils::Vector<Value, 8> args;
for (auto& sa : sargs) {
std::visit([&](auto&& v) { return args.Push(Val(v)); }, sa);
}
@@ -152,7 +149,7 @@
utils::Vector<const ast::Expression*, 8> args;
for (auto& a : c.args) {
- std::visit([&](auto&& v) { args.Push(v.Expr(*this)); }, a);
+ args.Push(a.Expr(*this));
}
auto* expr = Call(Source{{12, 34}}, sem::str(builtin), std::move(args));
@@ -173,14 +170,13 @@
// The result type of the constant-evaluated expression is a structure.
// Compare each of the fields individually.
for (size_t i = 0; i < expected_case.values.Length(); i++) {
- CheckConstant(value->Index(i), ToValueBase(expected_case.values[i]),
- expected_case.flags);
+ CheckConstant(value->Index(i), expected_case.values[i], expected_case.flags);
}
} else {
// Return type is not a structure. Just compare the single value
ASSERT_EQ(expected_case.values.Length(), 1u)
<< "const-eval returned non-struct, but Case expected multiple values";
- CheckConstant(value, ToValueBase(expected_case.values[0]), expected_case.flags);
+ CheckConstant(value, expected_case.values[0], expected_case.flags);
}
} else {
EXPECT_FALSE(r()->Resolve());
@@ -803,6 +799,33 @@
CrossCases<f16>()))));
template <typename T>
+std::vector<Case> DistanceCases() {
+ auto error_msg = [](auto a, const char* op, auto b) {
+ return "12:34 error: " + OverflowErrorMessage(a, op, b) + R"(
+12:34 note: when calculating distance)";
+ };
+
+ return std::vector<Case>{
+ C({T(0), T(0)}, T(0)),
+ // length(-5) -> 5
+ C({T(30), T(35)}, T(5)),
+
+ C({Vec(T(30), T(20)), Vec(T(25), T(15))}, Val(T(7.0710678119))).FloatComp(),
+
+ E({T::Lowest(), T::Highest()}, error_msg(T::Lowest(), "-", T::Highest())),
+ E({Vec(T::Highest(), T::Highest()), Vec(T(1), T(1))},
+ error_msg(T(T::Highest() - T(1)), "*", T(T::Highest() - T(1)))),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Distance,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kDistance),
+ testing::ValuesIn(Concat(DistanceCases<AFloat>(), //
+ DistanceCases<f32>(), //
+ DistanceCases<f16>()))));
+
+template <typename T>
std::vector<Case> DotCases() {
auto r = std::vector<Case>{
C({Vec(T(0), T(0)), Vec(T(0), T(0))}, Val(T(0))),
@@ -854,6 +877,83 @@
DotCases<f16>()))));
template <typename T>
+std::vector<Case> DeterminantCases() {
+ auto error_msg = [](auto a, const char* op, auto b) {
+ return "12:34 error: " + OverflowErrorMessage(a, op, b) + R"(
+12:34 note: when calculating determinant)";
+ };
+
+ auto r = std::vector<Case>{
+ // All zero == 0
+ C({Mat({T(0), T(0)}, //
+ {T(0), T(0)})}, //
+ Val(T(0))),
+
+ C({Mat({T(0), T(0), T(0)}, //
+ {T(0), T(0), T(0)}, //
+ {T(0), T(0), T(0)})}, //
+ Val(T(0))),
+
+ C({Mat({T(0), T(0), T(0), T(0)}, //
+ {T(0), T(0), T(0), T(0)}, //
+ {T(0), T(0), T(0), T(0)}, //
+ {T(0), T(0), T(0), T(0)})}, //
+ Val(T(0))),
+
+ // All same == 0
+ C({Mat({T(42), T(42)}, //
+ {T(42), T(42)})}, //
+ Val(T(0))),
+
+ C({Mat({T(42), T(42), T(42)}, //
+ {T(42), T(42), T(42)}, //
+ {T(42), T(42), T(42)})}, //
+ Val(T(0))),
+
+ C({Mat({T(42), T(42), T(42), T(42)}, //
+ {T(42), T(42), T(42), T(42)}, //
+ {T(42), T(42), T(42), T(42)}, //
+ {T(42), T(42), T(42), T(42)})}, //
+ Val(T(0))),
+
+ // Various values
+ C({Mat({-T(2), T(17)}, //
+ {T(5), T(45)})}, //
+ Val(-T(175))),
+
+ C({Mat({T(4), T(6), -T(13)}, //
+ {T(12), T(5), T(8)}, //
+ {T(9), T(17), T(16)})}, //
+ Val(-T(3011))),
+
+ C({Mat({T(2), T(9), T(8), T(1)}, //
+ {-T(4), T(11), -T(3), T(7)}, //
+ {T(6), T(5), T(12), -T(6)}, //
+ {T(3), -T(10), T(4), -T(7)})}, //
+ Val(T(469))),
+
+ // Overflow during multiply
+ E({Mat({T::Highest(), T(0)}, //
+ {T(0), T(2)})}, //
+ error_msg(T::Highest(), "*", T(2))),
+
+ // Overflow during subtract
+ E({Mat({T::Highest(), T::Lowest()}, //
+ {T(1), T(1)})}, //
+ error_msg(T::Highest(), "-", T::Lowest())),
+ };
+
+ return r;
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Determinant,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kDeterminant),
+ testing::ValuesIn(Concat(DeterminantCases<AFloat>(), //
+ DeterminantCases<f32>(), //
+ DeterminantCases<f16>()))));
+
+template <typename T>
std::vector<Case> FirstLeadingBitCases() {
using B = BitValues<T>;
auto r = std::vector<Case>{
@@ -970,6 +1070,87 @@
FloorCases<f16>()))));
template <typename T>
+std::vector<Case> FmaCases() {
+ auto error_msg = [](auto a, const char* op, auto b) {
+ return "12:34 error: " + OverflowErrorMessage(a, op, b) + R"(
+12:34 note: when calculating fma)";
+ };
+ return {
+ C({T(0), T(0), T(0)}, T(0)),
+ C({T(1), T(2), T(3)}, T(5)),
+ C({Vec(T(1), T(2.5), -T(1)), Vec(T(2), T(2.5), T(1)), Vec(T(4), T(3.75), -T(2))},
+ Vec(T(6), T(10), -T(3))),
+
+ E({T::Highest(), T::Highest(), T(0)}, error_msg(T::Highest(), "*", T::Highest())),
+ E({T::Highest(), T(1), T::Highest()}, error_msg(T::Highest(), "+", T::Highest())),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Fma,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kFma),
+ testing::ValuesIn(Concat(FmaCases<AFloat>(), //
+ FmaCases<f32>(),
+ FmaCases<f16>()))));
+
+template <typename T>
+std::vector<Case> FrexpCases() {
+ using F = T; // fract type
+ using E = std::conditional_t<std::is_same_v<T, AFloat>, AInt, i32>; // exp type
+
+ auto cases = std::vector<Case>{
+ // Scalar tests
+ // in fract exp
+ C({T(-3.5)}, {F(-0.875), E(2)}), //
+ C({T(-3.0)}, {F(-0.750), E(2)}), //
+ C({T(-2.5)}, {F(-0.625), E(2)}), //
+ C({T(-2.0)}, {F(-0.500), E(2)}), //
+ C({T(-1.5)}, {F(-0.750), E(1)}), //
+ C({T(-1.0)}, {F(-0.500), E(1)}), //
+ C({T(+0.0)}, {F(+0.000), E(0)}), //
+ C({T(+1.0)}, {F(+0.500), E(1)}), //
+ C({T(+1.5)}, {F(+0.750), E(1)}), //
+ C({T(+2.0)}, {F(+0.500), E(2)}), //
+ C({T(+2.5)}, {F(+0.625), E(2)}), //
+ C({T(+3.0)}, {F(+0.750), E(2)}), //
+ C({T(+3.5)}, {F(+0.875), E(2)}), //
+
+ // Vector tests
+ // in fract exp
+ C({Vec(T(-2.5), T(+1.0))}, {Vec(F(-0.625), F(+0.500)), Vec(E(2), E(1))}),
+ C({Vec(T(+3.5), T(-2.5))}, {Vec(F(+0.875), F(-0.625)), Vec(E(2), E(2))}),
+ };
+
+ ConcatIntoIf<std::is_same_v<T, f16>>(cases, std::vector<Case>{
+ C({T::Highest()}, {F(0x0.ffep0), E(16)}), //
+ C({T::Lowest()}, {F(-0x0.ffep0), E(16)}), //
+ C({T::Smallest()}, {F(0.5), E(-13)}), //
+ });
+
+ ConcatIntoIf<std::is_same_v<T, f32>>(cases,
+ std::vector<Case>{
+ C({T::Highest()}, {F(0x0.ffffffp0), E(128)}), //
+ C({T::Lowest()}, {F(-0x0.ffffffp0), E(128)}), //
+ C({T::Smallest()}, {F(0.5), E(-125)}), //
+ });
+
+ ConcatIntoIf<std::is_same_v<T, AFloat>>(
+ cases, std::vector<Case>{
+ C({T::Highest()}, {F(0x0.fffffffffffff8p0), E(1024)}), //
+ C({T::Lowest()}, {F(-0x0.fffffffffffff8p0), E(1024)}), //
+ C({T::Smallest()}, {F(0.5), E(-1021)}), //
+ });
+ return cases;
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Frexp,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kFrexp),
+ testing::ValuesIn(Concat(FrexpCases<AFloat>(), //
+ FrexpCases<f32>(), //
+ FrexpCases<f16>()))));
+
+template <typename T>
std::vector<Case> InsertBitsCases() {
using UT = Number<std::make_unsigned_t<UnwrapNumber<T>>>;
@@ -1051,6 +1232,28 @@
InsertBitsCases<u32>()))));
template <typename T>
+std::vector<Case> InverseSqrtCases() {
+ std::vector<Case> cases = {
+ C({T(25)}, T(.2)),
+
+ // Vector tests
+ C({Vec(T(25), T(100))}, Vec(T(.2), T(.1))),
+
+ E({T(0)}, "12:34 error: inverseSqrt must be called with a value > 0"),
+ E({-T(0)}, "12:34 error: inverseSqrt must be called with a value > 0"),
+ E({-T(25)}, "12:34 error: inverseSqrt must be called with a value > 0"),
+ };
+ return cases;
+}
+INSTANTIATE_TEST_SUITE_P( //
+ InverseSqrt,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kInverseSqrt),
+ testing::ValuesIn(Concat(InverseSqrtCases<AFloat>(), //
+ InverseSqrtCases<f32>(),
+ InverseSqrtCases<f16>()))));
+
+template <typename T>
std::vector<Case> DegreesAFloatCases() {
return std::vector<Case>{
C({T(0)}, T(0)), //
@@ -1102,6 +1305,46 @@
testing::ValuesIn(DegreesF16Cases<f16>())));
template <typename T>
+std::vector<Case> ExpCases() {
+ auto error_msg = [](auto a) { return "12:34 error: " + OverflowExpErrorMessage("e", a); };
+ return std::vector<Case>{C({T(0)}, T(1)), //
+ C({-T(0)}, T(1)), //
+ C({T(2)}, T(7.3890562)).FloatComp(),
+ C({-T(2)}, T(0.13533528)).FloatComp(), //
+ C({T::Lowest()}, T(0)),
+
+ E({T::Highest()}, error_msg(T::Highest()))};
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Exp,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kExp),
+ testing::ValuesIn(Concat(ExpCases<AFloat>(), //
+ ExpCases<f32>(),
+ ExpCases<f16>()))));
+
+template <typename T>
+std::vector<Case> Exp2Cases() {
+ auto error_msg = [](auto a) { return "12:34 error: " + OverflowExpErrorMessage("2", a); };
+ return std::vector<Case>{
+ C({T(0)}, T(1)), //
+ C({-T(0)}, T(1)), //
+ C({T(2)}, T(4.0)),
+ C({-T(2)}, T(0.25)), //
+ C({T::Lowest()}, T(0)),
+
+ E({T::Highest()}, error_msg(T::Highest())),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Exp2,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kExp2),
+ testing::ValuesIn(Concat(Exp2Cases<AFloat>(), //
+ Exp2Cases<f32>(),
+ Exp2Cases<f16>()))));
+
+template <typename T>
std::vector<Case> ExtractBitsCases() {
using UT = Number<std::make_unsigned_t<UnwrapNumber<T>>>;
@@ -1257,6 +1500,110 @@
LengthCases<f16>()))));
template <typename T>
+std::vector<Case> LogCases() {
+ auto error_msg = [] { return "12:34 error: log must be called with a value > 0"; };
+ return std::vector<Case>{C({T(1)}, T(0)), //
+ C({T(54.598150033)}, T(4)).FloatComp(0.002), //
+
+ E({T::Lowest()}, error_msg()), E({T(0)}, error_msg()),
+ E({-T(0)}, error_msg())};
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Log,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::ValuesIn(Concat(LogCases<AFloat>(), //
+ LogCases<f32>(),
+ LogCases<f16>()))));
+template <typename T>
+std::vector<Case> LogF16Cases() {
+ return std::vector<Case>{
+ C({T::Highest()}, T(11.085938)).FloatComp(),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ LogF16,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::ValuesIn(LogF16Cases<f16>())));
+template <typename T>
+std::vector<Case> LogF32Cases() {
+ return std::vector<Case>{
+ C({T::Highest()}, T(88.722839)).FloatComp(),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ LogF32,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::ValuesIn(LogF32Cases<f32>())));
+
+template <typename T>
+std::vector<Case> LogAbstractCases() {
+ return std::vector<Case>{
+ C({T::Highest()}, T(709.78271)).FloatComp(),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ LogAbstract,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog),
+ testing::ValuesIn(LogAbstractCases<AFloat>())));
+
+template <typename T>
+std::vector<Case> Log2Cases() {
+ auto error_msg = [] { return "12:34 error: log2 must be called with a value > 0"; };
+ return std::vector<Case>{
+ C({T(1)}, T(0)), //
+ C({T(4)}, T(2)), //
+
+ E({T::Lowest()}, error_msg()),
+ E({T(0)}, error_msg()),
+ E({-T(0)}, error_msg()),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Log2,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::ValuesIn(Concat(Log2Cases<AFloat>(), //
+ Log2Cases<f32>(),
+ Log2Cases<f16>()))));
+template <typename T>
+std::vector<Case> Log2F16Cases() {
+ return std::vector<Case>{
+ C({T::Highest()}, T(15.9922)).FloatComp(),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Log2F16,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::ValuesIn(Log2F16Cases<f16>())));
+template <typename T>
+std::vector<Case> Log2F32Cases() {
+ return std::vector<Case>{
+ C({T::Highest()}, T(128)).FloatComp(),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Log2F32,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::ValuesIn(Log2F32Cases<f32>())));
+template <typename T>
+std::vector<Case> Log2AbstractCases() {
+ return std::vector<Case>{
+ C({T::Highest()}, T(1024)).FloatComp(),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Log2Abstract,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kLog2),
+ testing::ValuesIn(Log2AbstractCases<AFloat>())));
+
+template <typename T>
std::vector<Case> MaxCases() {
return {
C({T(0), T(0)}, T(0)),
@@ -1339,9 +1686,40 @@
Modf,
ResolverConstEvalBuiltinTest,
testing::Combine(testing::Values(sem::BuiltinType::kModf),
- testing::ValuesIn(Concat(ModfCases<f32>(), //
+ testing::ValuesIn(Concat(ModfCases<AFloat>(), //
+ ModfCases<f32>(), //
ModfCases<f16>()))));
+template <typename T>
+std::vector<Case> NormalizeCases() {
+ auto error_msg = [&](auto a) {
+ return "12:34 error: " + OverflowErrorMessage(a, "*", a) + R"(
+12:34 note: when calculating normalize)";
+ };
+
+ return {
+ C({Vec(T(2), T(4), T(2))}, Vec(T(0.4082482905), T(0.8164965809), T(0.4082482905)))
+ .FloatComp(),
+
+ C({Vec(T(2), T(0), T(0))}, Vec(T(1), T(0), T(0))),
+ C({Vec(T(0), T(2), T(0))}, Vec(T(0), T(1), T(0))),
+ C({Vec(T(0), T(0), T(2))}, Vec(T(0), T(0), T(1))),
+ C({Vec(-T(2), T(0), T(0))}, Vec(-T(1), T(0), T(0))),
+ C({Vec(T(0), -T(2), T(0))}, Vec(T(0), -T(1), T(0))),
+ C({Vec(T(0), T(0), -T(2))}, Vec(T(0), T(0), -T(1))),
+
+ E({Vec(T(0), T(0), T(0))}, "12:34 error: zero length vector can not be normalized"),
+ E({Vec(T::Highest(), T::Highest(), T::Highest())}, error_msg(T::Highest())),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Normalize,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kNormalize),
+ testing::ValuesIn(Concat(NormalizeCases<AFloat>(), //
+ NormalizeCases<f32>(), //
+ NormalizeCases<f16>()))));
+
std::vector<Case> Pack4x8snormCases() {
return {
C({Vec(f32(0), f32(0), f32(0), f32(0))}, Val(u32(0x0000'0000))),
@@ -1815,6 +2193,72 @@
TanhCases<f16>()))));
template <typename T>
+std::vector<Case> TransposeCases() {
+ return {
+ // 2x2
+ C({Mat({T(1), T(2)}, //
+ {T(3), T(4)})}, //
+ Mat({T(1), T(3)}, //
+ {T(2), T(4)})),
+
+ // 3x3
+ C({Mat({T(1), T(2), T(3)}, //
+ {T(4), T(5), T(6)}, //
+ {T(7), T(8), T(9)})}, //
+ Mat({T(1), T(4), T(7)}, //
+ {T(2), T(5), T(8)}, //
+ {T(3), T(6), T(9)})),
+
+ // 4x4
+ C({Mat({T(1), T(2), T(3), T(4)}, //
+ {T(5), T(6), T(7), T(8)}, //
+ {T(9), T(10), T(11), T(12)}, //
+ {T(13), T(14), T(15), T(16)})}, //
+ Mat({T(1), T(5), T(9), T(13)}, //
+ {T(2), T(6), T(10), T(14)}, //
+ {T(3), T(7), T(11), T(15)}, //
+ {T(4), T(8), T(12), T(16)})),
+
+ // 4x2
+ C({Mat({T(1), T(2), T(3), T(4)}, //
+ {T(5), T(6), T(7), T(8)})}, //
+ Mat({T(1), T(5)}, //
+ {T(2), T(6)}, //
+ {T(3), T(7)}, //
+ {T(4), T(8)})),
+
+ // 2x4
+ C({Mat({T(1), T(2)}, //
+ {T(3), T(4)}, //
+ {T(5), T(6)}, //
+ {T(7), T(8)})}, //
+ Mat({T(1), T(3), T(5), T(7)}, //
+ {T(2), T(4), T(6), T(8)})),
+
+ // 3x2
+ C({Mat({T(1), T(2), T(3)}, //
+ {T(4), T(5), T(6)})}, //
+ Mat({T(1), T(4)}, //
+ {T(2), T(5)}, //
+ {T(3), T(6)})),
+
+ // 2x3
+ C({Mat({T(1), T(2)}, //
+ {T(3), T(4)}, //
+ {T(5), T(6)})}, //
+ Mat({T(1), T(3), T(5)}, //
+ {T(2), T(4), T(6)})),
+ };
+}
+INSTANTIATE_TEST_SUITE_P( //
+ Transpose,
+ ResolverConstEvalBuiltinTest,
+ testing::Combine(testing::Values(sem::BuiltinType::kTranspose),
+ testing::ValuesIn(Concat(TransposeCases<AFloat>(), //
+ TransposeCases<f32>(),
+ TransposeCases<f16>()))));
+
+template <typename T>
std::vector<Case> TruncCases() {
std::vector<Case> cases = {C({T(0)}, T(0)), //
C({-T(0)}, -T(0)), //
diff --git a/src/tint/resolver/const_eval_conversion_test.cc b/src/tint/resolver/const_eval_conversion_test.cc
index ed68725..da37f3b 100644
--- a/src/tint/resolver/const_eval_conversion_test.cc
+++ b/src/tint/resolver/const_eval_conversion_test.cc
@@ -19,19 +19,6 @@
namespace tint::resolver {
namespace {
-using Scalar = std::variant< //
- builder::Value<AInt>,
- builder::Value<AFloat>,
- builder::Value<u32>,
- builder::Value<i32>,
- builder::Value<f32>,
- builder::Value<f16>,
- builder::Value<bool>>;
-
-static std::ostream& operator<<(std::ostream& o, const Scalar& scalar) {
- return ToValueBase(scalar)->Print(o);
-}
-
enum class Kind {
kScalar,
kVector,
@@ -48,8 +35,8 @@
}
struct Case {
- Scalar input;
- Scalar expected;
+ Value input;
+ Value expected;
builder::CreatePtrs type;
bool unrepresentable = false;
};
@@ -65,7 +52,7 @@
template <typename TO, typename FROM>
Case Success(FROM input, TO expected) {
- return {builder::Val(input), builder::Val(expected), builder::CreatePtrsFor<TO>()};
+ return {Val(input), Val(expected), builder::CreatePtrsFor<TO>()};
}
template <typename TO, typename FROM>
@@ -83,7 +70,7 @@
const auto& type = std::get<1>(GetParam()).type;
const auto unrepresentable = std::get<1>(GetParam()).unrepresentable;
- auto* input_val = ToValueBase(input)->Expr(*this);
+ auto* input_val = input.Expr(*this);
auto* expr = Construct(type.ast(*this), input_val);
if (kind == Kind::kVector) {
expr = Construct(ty.vec(nullptr, 3), expr);
@@ -107,7 +94,7 @@
ASSERT_NE(sem->ConstantValue(), nullptr);
EXPECT_TYPE(sem->ConstantValue()->Type(), target_sem_ty);
- auto expected_values = ToValueBase(expected)->Args();
+ auto expected_values = expected.Args();
if (kind == Kind::kVector) {
expected_values.values.Push(expected_values.values[0]);
expected_values.values.Push(expected_values.values[0]);
diff --git a/src/tint/resolver/const_eval_test.h b/src/tint/resolver/const_eval_test.h
index bc85542..dcb91d0 100644
--- a/src/tint/resolver/const_eval_test.h
+++ b/src/tint/resolver/const_eval_test.h
@@ -88,10 +88,10 @@
/// @param expected_value the expected value for the test
/// @param flags optional flags for controlling the comparisons
inline void CheckConstant(const sem::Constant* got_constant,
- const builder::ValueBase* expected_value,
+ const builder::Value& expected_value,
CheckConstantFlags flags = {}) {
auto values_flat = ScalarArgsFrom(got_constant);
- auto expected_values_flat = expected_value->Args();
+ auto expected_values_flat = expected_value.Args();
ASSERT_EQ(values_flat.values.Length(), expected_values_flat.values.Length());
for (size_t i = 0; i < values_flat.values.Length(); ++i) {
auto& got_scalar = values_flat.values[i];
@@ -223,7 +223,7 @@
return ss.str();
}
-/// Returns the overflow error message for converions
+/// Returns the overflow error message for conversions
template <typename VALUE_TY>
std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) {
std::stringstream ss;
@@ -233,77 +233,22 @@
return ss.str();
}
+/// Returns the overflow error message for exponentiation
+template <typename NumberT>
+std::string OverflowExpErrorMessage(std::string_view base, NumberT value) {
+ std::stringstream ss;
+ ss << std::setprecision(20);
+ ss << base << "^" << value << " cannot be represented as "
+ << "'" << FriendlyName<NumberT>() << "'";
+ return ss.str();
+}
+
using builder::IsValue;
using builder::Mat;
using builder::Val;
using builder::Value;
-using builder::ValueBase;
using builder::Vec;
-using Types = std::variant< //
- Value<AInt>,
- Value<AFloat>,
- Value<u32>,
- Value<i32>,
- Value<f32>,
- Value<f16>,
- Value<bool>,
-
- Value<builder::vec2<AInt>>,
- Value<builder::vec2<AFloat>>,
- Value<builder::vec2<u32>>,
- Value<builder::vec2<i32>>,
- Value<builder::vec2<f32>>,
- Value<builder::vec2<f16>>,
- Value<builder::vec2<bool>>,
-
- Value<builder::vec3<AInt>>,
- Value<builder::vec3<AFloat>>,
- Value<builder::vec3<u32>>,
- Value<builder::vec3<i32>>,
- Value<builder::vec3<f32>>,
- Value<builder::vec3<f16>>,
- Value<builder::vec3<bool>>,
-
- Value<builder::vec4<AInt>>,
- Value<builder::vec4<AFloat>>,
- Value<builder::vec4<u32>>,
- Value<builder::vec4<i32>>,
- Value<builder::vec4<f32>>,
- Value<builder::vec4<f16>>,
- Value<builder::vec4<bool>>,
-
- Value<builder::mat2x2<AInt>>,
- Value<builder::mat2x2<AFloat>>,
- Value<builder::mat2x2<f32>>,
- Value<builder::mat2x2<f16>>,
-
- Value<builder::mat2x3<AInt>>,
- Value<builder::mat2x3<AFloat>>,
- Value<builder::mat2x3<f32>>,
- Value<builder::mat2x3<f16>>,
-
- Value<builder::mat3x2<AInt>>,
- Value<builder::mat3x2<AFloat>>,
- Value<builder::mat3x2<f32>>,
- Value<builder::mat3x2<f16>>
- //
- >;
-
-/// Returns the current Value<T> in the `types` variant as a `ValueBase` pointer to use the
-/// polymorphic API. This trades longer compile times using std::variant for longer runtime via
-/// virtual function calls.
-template <typename ValueVariant>
-inline const ValueBase* ToValueBase(const ValueVariant& types) {
- return std::visit(
- [](auto&& t) -> const ValueBase* { return static_cast<const ValueBase*>(&t); }, types);
-}
-
-/// Prints Types to ostream
-inline std::ostream& operator<<(std::ostream& o, const Types& types) {
- return ToValueBase(types)->Print(o);
-}
-
// Calls `f` on deepest elements of both `a` and `b`. If function returns Action::kStop, it stops
// traversing, and return Action::kStop; if the function returns Action::kContinue, it continues and
// returns Action::kContinue when done.
diff --git a/src/tint/resolver/const_eval_unary_op_test.cc b/src/tint/resolver/const_eval_unary_op_test.cc
index fced490..d24c27b 100644
--- a/src/tint/resolver/const_eval_unary_op_test.cc
+++ b/src/tint/resolver/const_eval_unary_op_test.cc
@@ -19,22 +19,17 @@
namespace tint::resolver {
namespace {
-// Bring in std::ostream& operator<<(std::ostream& o, const Types& types)
-using resolver::operator<<;
-
struct Case {
- Types input;
- Types expected;
+ Value input;
+ Value expected;
};
static std::ostream& operator<<(std::ostream& o, const Case& c) {
o << "input: " << c.input << ", expected: " << c.expected;
return o;
}
-
-/// Creates a Case with Values of any type
-template <typename T, typename U>
-Case C(Value<T> input, Value<U> expected) {
+// Creates a Case with Values of any type
+Case C(Value input, Value expected) {
return Case{std::move(input), std::move(expected)};
}
@@ -52,10 +47,10 @@
auto op = std::get<0>(GetParam());
auto& c = std::get<1>(GetParam());
- auto* expected = ToValueBase(c.expected);
- auto* input = ToValueBase(c.input);
+ auto& expected = c.expected;
+ auto& input = c.input;
- auto* input_expr = input->Expr(*this);
+ auto* input_expr = input.Expr(*this);
auto* expr = create<ast::UnaryOpExpression>(op, input_expr);
GlobalConst("C", expr);
@@ -67,13 +62,13 @@
EXPECT_TYPE(value->Type(), sem->Type());
auto values_flat = ScalarArgsFrom(value);
- auto expected_values_flat = expected->Args();
+ auto expected_values_flat = expected.Args();
ASSERT_EQ(values_flat.values.Length(), expected_values_flat.values.Length());
for (size_t i = 0; i < values_flat.values.Length(); ++i) {
auto& a = values_flat.values[i];
auto& b = expected_values_flat.values[i];
EXPECT_EQ(a, b);
- if (expected->IsIntegral()) {
+ if (expected.IsIntegral()) {
// Check that the constant's integer doesn't contain unexpected
// data in the MSBs that are outside of the bit-width of T.
EXPECT_EQ(builder::As<AInt>(a), builder::As<AInt>(b));
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index 1fda54f..796412b 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -471,7 +471,7 @@
}
}
- if (auto* global = globals_.Find(to); global && (*global)->node == resolved) {
+ if (auto global = globals_.Find(to); global && (*global)->node == resolved) {
if (dependency_edges_.Add(DependencyEdge{current_global_, *global},
DependencyInfo{from->source, action})) {
current_global_->deps.Push(*global);
diff --git a/src/tint/resolver/dependency_graph_test.cc b/src/tint/resolver/dependency_graph_test.cc
index 2cc4a3a..81e79ff 100644
--- a/src/tint/resolver/dependency_graph_test.cc
+++ b/src/tint/resolver/dependency_graph_test.cc
@@ -1128,8 +1128,8 @@
if (expect_pass) {
// Check that the use resolves to the declaration
- auto* resolved_symbol = graph.resolved_symbols.Find(use);
- ASSERT_NE(resolved_symbol, nullptr);
+ auto resolved_symbol = graph.resolved_symbols.Find(use);
+ ASSERT_TRUE(resolved_symbol);
EXPECT_EQ(*resolved_symbol, decl)
<< "resolved: " << (*resolved_symbol ? (*resolved_symbol)->TypeInfo().name : "<null>")
<< "\n"
@@ -1179,8 +1179,8 @@
helper.Build();
auto shadows = Build().shadows;
- auto* shadow = shadows.Find(inner_var);
- ASSERT_NE(shadow, nullptr);
+ auto shadow = shadows.Find(inner_var);
+ ASSERT_TRUE(shadow);
EXPECT_EQ(*shadow, outer);
}
@@ -1310,8 +1310,8 @@
auto graph = Build();
for (auto use : symbol_uses) {
- auto* resolved_symbol = graph.resolved_symbols.Find(use.use);
- ASSERT_NE(resolved_symbol, nullptr) << use.where;
+ auto resolved_symbol = graph.resolved_symbols.Find(use.use);
+ ASSERT_TRUE(resolved_symbol) << use.where;
EXPECT_EQ(*resolved_symbol, use.decl) << use.where;
}
}
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index 9d11e08..a04eca4 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -796,20 +796,20 @@
std::string name;
const sem::Type* type;
};
-const sem::Struct* build_struct(MatchState& state,
- std::string name,
- std::initializer_list<NameAndType> member_names_and_types) {
+sem::Struct* build_struct(ProgramBuilder& b,
+ std::string name,
+ std::initializer_list<NameAndType> member_names_and_types) {
uint32_t offset = 0;
uint32_t max_align = 0;
sem::StructMemberList members;
for (auto& m : member_names_and_types) {
- uint32_t align = m.type->Align();
+ uint32_t align = std::max<uint32_t>(m.type->Align(), 1);
uint32_t size = m.type->Size();
offset = utils::RoundUp(align, offset);
max_align = std::max(max_align, align);
- members.emplace_back(state.builder.create<sem::StructMember>(
+ members.emplace_back(b.create<sem::StructMember>(
/* declaration */ nullptr,
- /* name */ state.builder.Sym(m.name),
+ /* name */ b.Sym(m.name),
/* type */ m.type,
/* index */ static_cast<uint32_t>(members.size()),
/* offset */ offset,
@@ -820,9 +820,9 @@
}
uint32_t size_without_padding = offset;
uint32_t size_with_padding = utils::RoundUp(max_align, offset);
- return state.builder.create<sem::Struct>(
+ return b.create<sem::Struct>(
/* declaration */ nullptr,
- /* name */ state.builder.Sym(name),
+ /* name */ b.Sym(name),
/* members */ members,
/* align */ max_align,
/* size */ size_with_padding,
@@ -830,48 +830,128 @@
}
const sem::Struct* build_modf_result(MatchState& state, const sem::Type* el) {
- std::string display_name;
- if (el->Is<sem::F16>()) {
- display_name = "__modf_result_f16";
- } else {
- display_name = "__modf_result";
- }
- return build_struct(state, display_name, {{"fract", el}, {"whole", el}});
+ auto build_f32 = [&] {
+ auto* ty = state.builder.create<sem::F32>();
+ return build_struct(state.builder, "__modf_result_f32", {{"fract", ty}, {"whole", ty}});
+ };
+ auto build_f16 = [&] {
+ auto* ty = state.builder.create<sem::F16>();
+ return build_struct(state.builder, "__modf_result_f16", {{"fract", ty}, {"whole", ty}});
+ };
+
+ return Switch(
+ el, //
+ [&](const sem::F32*) { return build_f32(); }, //
+ [&](const sem::F16*) { return build_f16(); }, //
+ [&](const sem::AbstractFloat*) {
+ auto* abstract = build_struct(state.builder, "__modf_result_abstract",
+ {{"fract", el}, {"whole", el}});
+ abstract->SetConcreteTypes(utils::Vector{build_f32(), build_f16()});
+ return abstract;
+ },
+ [&](Default) {
+ TINT_ICE(Resolver, state.builder.Diagnostics())
+ << "unhandled modf type: " << state.builder.FriendlyName(el);
+ return nullptr;
+ });
}
+
const sem::Struct* build_modf_result_vec(MatchState& state, Number& n, const sem::Type* el) {
- std::string display_name;
- if (el->Is<sem::F16>()) {
- display_name = "__modf_result_vec" + std::to_string(n.Value()) + "_f16";
- } else {
- display_name = "__modf_result_vec" + std::to_string(n.Value());
- }
- auto* vec = state.builder.create<sem::Vector>(el, n.Value());
- return build_struct(state, display_name, {{"fract", vec}, {"whole", vec}});
+ auto prefix = "__modf_result_vec" + std::to_string(n.Value());
+ auto build_f32 = [&] {
+ auto* vec = state.builder.create<sem::Vector>(state.builder.create<sem::F32>(), n.Value());
+ return build_struct(state.builder, prefix + "_f32", {{"fract", vec}, {"whole", vec}});
+ };
+ auto build_f16 = [&] {
+ auto* vec = state.builder.create<sem::Vector>(state.builder.create<sem::F16>(), n.Value());
+ return build_struct(state.builder, prefix + "_f16", {{"fract", vec}, {"whole", vec}});
+ };
+
+ return Switch(
+ el, //
+ [&](const sem::F32*) { return build_f32(); }, //
+ [&](const sem::F16*) { return build_f16(); }, //
+ [&](const sem::AbstractFloat*) {
+ auto* vec = state.builder.create<sem::Vector>(el, n.Value());
+ auto* abstract =
+ build_struct(state.builder, prefix + "_abstract", {{"fract", vec}, {"whole", vec}});
+ abstract->SetConcreteTypes(utils::Vector{build_f32(), build_f16()});
+ return abstract;
+ },
+ [&](Default) {
+ TINT_ICE(Resolver, state.builder.Diagnostics())
+ << "unhandled modf type: " << state.builder.FriendlyName(el);
+ return nullptr;
+ });
}
+
const sem::Struct* build_frexp_result(MatchState& state, const sem::Type* el) {
- std::string display_name;
- if (el->Is<sem::F16>()) {
- display_name = "__frexp_result_f16";
- } else {
- display_name = "__frexp_result";
- }
- auto* i32 = state.builder.create<sem::I32>();
- return build_struct(state, display_name, {{"fract", el}, {"exp", i32}});
+ auto build_f32 = [&] {
+ auto* f = state.builder.create<sem::F32>();
+ auto* i = state.builder.create<sem::I32>();
+ return build_struct(state.builder, "__frexp_result_f32", {{"fract", f}, {"exp", i}});
+ };
+ auto build_f16 = [&] {
+ auto* f = state.builder.create<sem::F16>();
+ auto* i = state.builder.create<sem::I32>();
+ return build_struct(state.builder, "__frexp_result_f16", {{"fract", f}, {"exp", i}});
+ };
+
+ return Switch(
+ el, //
+ [&](const sem::F32*) { return build_f32(); }, //
+ [&](const sem::F16*) { return build_f16(); }, //
+ [&](const sem::AbstractFloat*) {
+ auto* i = state.builder.create<sem::AbstractInt>();
+ auto* abstract =
+ build_struct(state.builder, "__frexp_result_abstract", {{"fract", el}, {"exp", i}});
+ abstract->SetConcreteTypes(utils::Vector{build_f32(), build_f16()});
+ return abstract;
+ },
+ [&](Default) {
+ TINT_ICE(Resolver, state.builder.Diagnostics())
+ << "unhandled frexp type: " << state.builder.FriendlyName(el);
+ return nullptr;
+ });
}
+
const sem::Struct* build_frexp_result_vec(MatchState& state, Number& n, const sem::Type* el) {
- std::string display_name;
- if (el->Is<sem::F16>()) {
- display_name = "__frexp_result_vec" + std::to_string(n.Value()) + "_f16";
- } else {
- display_name = "__frexp_result_vec" + std::to_string(n.Value());
- }
- auto* vec = state.builder.create<sem::Vector>(el, n.Value());
- auto* vec_i32 = state.builder.create<sem::Vector>(state.builder.create<sem::I32>(), n.Value());
- return build_struct(state, display_name, {{"fract", vec}, {"exp", vec_i32}});
+ auto prefix = "__frexp_result_vec" + std::to_string(n.Value());
+ auto build_f32 = [&] {
+ auto* f = state.builder.create<sem::Vector>(state.builder.create<sem::F32>(), n.Value());
+ auto* e = state.builder.create<sem::Vector>(state.builder.create<sem::I32>(), n.Value());
+ return build_struct(state.builder, prefix + "_f32", {{"fract", f}, {"exp", e}});
+ };
+ auto build_f16 = [&] {
+ auto* f = state.builder.create<sem::Vector>(state.builder.create<sem::F16>(), n.Value());
+ auto* e = state.builder.create<sem::Vector>(state.builder.create<sem::I32>(), n.Value());
+ return build_struct(state.builder, prefix + "_f16", {{"fract", f}, {"exp", e}});
+ };
+
+ return Switch(
+ el, //
+ [&](const sem::F32*) { return build_f32(); }, //
+ [&](const sem::F16*) { return build_f16(); }, //
+ [&](const sem::AbstractFloat*) {
+ auto* f = state.builder.create<sem::Vector>(el, n.Value());
+ auto* e = state.builder.create<sem::Vector>(state.builder.create<sem::AbstractInt>(),
+ n.Value());
+ auto* abstract =
+ build_struct(state.builder, prefix + "_abstract", {{"fract", f}, {"exp", e}});
+ abstract->SetConcreteTypes(utils::Vector{build_f32(), build_f16()});
+ return abstract;
+ },
+ [&](Default) {
+ TINT_ICE(Resolver, state.builder.Diagnostics())
+ << "unhandled frexp type: " << state.builder.FriendlyName(el);
+ return nullptr;
+ });
}
+
const sem::Struct* build_atomic_compare_exchange_result(MatchState& state, const sem::Type* ty) {
return build_struct(
- state, "__atomic_compare_exchange_result" + ty->FriendlyName(state.builder.Symbols()),
+ state.builder,
+ "__atomic_compare_exchange_result" + ty->FriendlyName(state.builder.Symbols()),
{{"old_value", const_cast<sem::Type*>(ty)},
{"exchanged", state.builder.create<sem::Bool>()}});
}
diff --git a/src/tint/resolver/intrinsic_table.h b/src/tint/resolver/intrinsic_table.h
index a873df9..05ca8d2 100644
--- a/src/tint/resolver/intrinsic_table.h
+++ b/src/tint/resolver/intrinsic_table.h
@@ -148,7 +148,6 @@
/// `sem::EvaluationStage::kRuntime`, then only overloads with concrete argument types
/// will be considered, as all abstract-numerics will have been materialized
/// after shader creation time (sem::EvaluationStage::kConstant).
-
/// @param source the source of the call
/// @return a sem::TypeInitializer, sem::TypeConversion or nullptr if nothing matched
virtual InitOrConv Lookup(InitConvIntrinsic type,
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index be0e4bb..9d77df3 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -12198,24 +12198,24 @@
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[600],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::distance,
},
{
/* [324] */
/* num parameters */ 2,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[602],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::distance,
},
{
/* [325] */
@@ -12366,48 +12366,48 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[850],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::exp,
},
{
/* [338] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[851],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::exp,
},
{
/* [339] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[852],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::exp2,
},
{
/* [340] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[853],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::exp2,
},
{
/* [341] */
@@ -12510,24 +12510,24 @@
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[462],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::fma,
},
{
/* [350] */
/* num parameters */ 3,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[465],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::fma,
},
{
/* [351] */
@@ -12558,24 +12558,24 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[862],
/* return matcher indices */ &kMatcherIndices[104],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::frexp,
},
{
/* [354] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[863],
/* return matcher indices */ &kMatcherIndices[39],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::frexp,
},
{
/* [355] */
@@ -12678,24 +12678,24 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[870],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::inverseSqrt,
},
{
/* [364] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[871],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::inverseSqrt,
},
{
/* [365] */
@@ -12750,48 +12750,48 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[874],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::log,
},
{
/* [370] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[875],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::log,
},
{
/* [371] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[876],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::log2,
},
{
/* [372] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[877],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::log2,
},
{
/* [373] */
@@ -12846,7 +12846,7 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[878],
/* return matcher indices */ &kMatcherIndices[106],
@@ -12858,7 +12858,7 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[879],
/* return matcher indices */ &kMatcherIndices[45],
@@ -13566,12 +13566,12 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[837],
/* return matcher indices */ &kMatcherIndices[3],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::determinant,
},
{
/* [438] */
@@ -13626,12 +13626,12 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[4],
/* parameters */ &kParameters[880],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::normalize,
},
{
/* [443] */
@@ -13734,12 +13734,12 @@
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 2,
- /* template types */ &kTemplateTypes[26],
+ /* template types */ &kTemplateTypes[23],
/* template numbers */ &kTemplateNumbers[3],
/* parameters */ &kParameters[908],
/* return matcher indices */ &kMatcherIndices[18],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
- /* const eval */ nullptr,
+ /* const eval */ &ConstEval::transpose,
},
{
/* [452] */
@@ -14124,14 +14124,14 @@
},
{
/* [20] */
- /* fn determinant<N : num, T : f32_f16>(mat<N, N, T>) -> T */
+ /* fn determinant<N : num, T : fa_f32_f16>(mat<N, N, T>) -> T */
/* num overloads */ 1,
/* overloads */ &kOverloads[437],
},
{
/* [21] */
- /* fn distance<T : f32_f16>(T, T) -> T */
- /* fn distance<N : num, T : f32_f16>(vec<N, T>, vec<N, T>) -> T */
+ /* fn distance<T : fa_f32_f16>(T, T) -> T */
+ /* fn distance<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>) -> T */
/* num overloads */ 2,
/* overloads */ &kOverloads[323],
},
@@ -14197,15 +14197,15 @@
},
{
/* [31] */
- /* fn exp<T : f32_f16>(T) -> T */
- /* fn exp<N : num, T : f32_f16>(vec<N, T>) -> vec<N, T> */
+ /* fn exp<T : fa_f32_f16>(T) -> T */
+ /* fn exp<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[337],
},
{
/* [32] */
- /* fn exp2<T : f32_f16>(T) -> T */
- /* fn exp2<N : num, T : f32_f16>(vec<N, T>) -> vec<N, T> */
+ /* fn exp2<T : fa_f32_f16>(T) -> T */
+ /* fn exp2<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[339],
},
@@ -14245,8 +14245,8 @@
},
{
/* [38] */
- /* fn fma<T : f32_f16>(T, T, T) -> T */
- /* fn fma<N : num, T : f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T> */
+ /* fn fma<T : fa_f32_f16>(T, T, T) -> T */
+ /* fn fma<N : num, T : fa_f32_f16>(vec<N, T>, vec<N, T>, vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[349],
},
@@ -14259,8 +14259,8 @@
},
{
/* [40] */
- /* fn frexp<T : f32_f16>(T) -> __frexp_result<T> */
- /* fn frexp<N : num, T : f32_f16>(vec<N, T>) -> __frexp_result_vec<N, T> */
+ /* fn frexp<T : fa_f32_f16>(T) -> __frexp_result<T> */
+ /* fn frexp<N : num, T : fa_f32_f16>(vec<N, T>) -> __frexp_result_vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[353],
},
@@ -14294,8 +14294,8 @@
},
{
/* [45] */
- /* fn inverseSqrt<T : f32_f16>(T) -> T */
- /* fn inverseSqrt<N : num, T : f32_f16>(vec<N, T>) -> vec<N, T> */
+ /* fn inverseSqrt<T : fa_f32_f16>(T) -> T */
+ /* fn inverseSqrt<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[363],
},
@@ -14315,15 +14315,15 @@
},
{
/* [48] */
- /* fn log<T : f32_f16>(T) -> T */
- /* fn log<N : num, T : f32_f16>(vec<N, T>) -> vec<N, T> */
+ /* fn log<T : fa_f32_f16>(T) -> T */
+ /* fn log<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[369],
},
{
/* [49] */
- /* fn log2<T : f32_f16>(T) -> T */
- /* fn log2<N : num, T : f32_f16>(vec<N, T>) -> vec<N, T> */
+ /* fn log2<T : fa_f32_f16>(T) -> T */
+ /* fn log2<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[371],
},
@@ -14351,14 +14351,14 @@
},
{
/* [53] */
- /* fn modf<T : f32_f16>(@test_value(-1.5) T) -> __modf_result<T> */
- /* fn modf<N : num, T : f32_f16>(@test_value(-1.5) vec<N, T>) -> __modf_result_vec<N, T> */
+ /* fn modf<T : fa_f32_f16>(@test_value(-1.5) T) -> __modf_result<T> */
+ /* fn modf<N : num, T : fa_f32_f16>(@test_value(-1.5) vec<N, T>) -> __modf_result_vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[377],
},
{
/* [54] */
- /* fn normalize<N : num, T : f32_f16>(vec<N, T>) -> vec<N, T> */
+ /* fn normalize<N : num, T : fa_f32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 1,
/* overloads */ &kOverloads[442],
},
@@ -14518,7 +14518,7 @@
},
{
/* [78] */
- /* fn transpose<M : num, N : num, T : f32_f16>(mat<M, N, T>) -> mat<N, M, T> */
+ /* fn transpose<M : num, N : num, T : fa_f32_f16>(mat<M, N, T>) -> mat<N, M, T> */
/* num overloads */ 1,
/* overloads */ &kOverloads[451],
},
diff --git a/src/tint/resolver/materialize_test.cc b/src/tint/resolver/materialize_test.cc
index a2084a4..be8d400 100644
--- a/src/tint/resolver/materialize_test.cc
+++ b/src/tint/resolver/materialize_test.cc
@@ -1236,5 +1236,179 @@
} // namespace materialize_abstract_numeric_to_unrelated_type
+////////////////////////////////////////////////////////////////////////////////
+// Materialization tests for builtin-returned abstract structures
+// These are too bespoke to slot into the more general materialization tests above
+////////////////////////////////////////////////////////////////////////////////
+namespace materialize_abstract_structure {
+
+using MaterializeAbstractStructure = resolver::ResolverTest;
+
+TEST_F(MaterializeAbstractStructure, Modf_Scalar_DefaultType) {
+ // var v = modf(1);
+ auto* call = Call("modf", 1_a);
+ WrapInFunction(Decl(Var("v", call)));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::F32>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::AbstractFloat>());
+}
+
+TEST_F(MaterializeAbstractStructure, Modf_Vector_DefaultType) {
+ // var v = modf(vec2(1));
+ auto* call = Call("modf", Construct(ty.vec2(nullptr), 1_a));
+ WrapInFunction(Decl(Var("v", call)));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::F32>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(
+ abstract_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::AbstractFloat>());
+}
+
+TEST_F(MaterializeAbstractStructure, Modf_Scalar_ExplicitType) {
+ // var v = modf(1_h); // v is __modf_result_f16
+ // v = modf(1); // __modf_result_f16 <- __modf_result_abstract
+ Enable(ast::Extension::kF16);
+ auto* call = Call("modf", 1_a);
+ WrapInFunction(Decl(Var("v", Call("modf", 1_h))), //
+ Assign("v", call));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::F16>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::AbstractFloat>());
+}
+
+TEST_F(MaterializeAbstractStructure, Modf_Vector_ExplicitType) {
+ // var v = modf(vec2(1_h)); // v is __modf_result_vec2_f16
+ // v = modf(vec2(1)); // __modf_result_vec2_f16 <- __modf_result_vec2_abstract
+ Enable(ast::Extension::kF16);
+ auto* call = Call("modf", Construct(ty.vec2(nullptr), 1_a));
+ WrapInFunction(Decl(Var("v", Call("modf", Construct(ty.vec2(nullptr), 1_h)))),
+ Assign("v", call));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::F16>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(
+ abstract_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::AbstractFloat>());
+}
+
+TEST_F(MaterializeAbstractStructure, Frexp_Scalar_DefaultType) {
+ // var v = frexp(1);
+ auto* call = Call("frexp", 1_a);
+ WrapInFunction(Decl(Var("v", call)));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::F32>());
+ ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<sem::I32>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::AbstractFloat>());
+ ASSERT_TRUE(abstract_str->Members()[1]->Type()->Is<sem::AbstractInt>());
+}
+
+TEST_F(MaterializeAbstractStructure, Frexp_Vector_DefaultType) {
+ // var v = frexp(vec2(1));
+ auto* call = Call("frexp", Construct(ty.vec2(nullptr), 1_a));
+ WrapInFunction(Decl(Var("v", call)));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::F32>());
+ ASSERT_TRUE(concrete_str->Members()[1]->Type()->As<sem::Vector>()->type()->Is<sem::I32>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(
+ abstract_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::AbstractFloat>());
+ ASSERT_TRUE(
+ abstract_str->Members()[1]->Type()->As<sem::Vector>()->type()->Is<sem::AbstractInt>());
+}
+
+TEST_F(MaterializeAbstractStructure, Frexp_Scalar_ExplicitType) {
+ // var v = frexp(1_h); // v is __frexp_result_f16
+ // v = frexp(1); // __frexp_result_f16 <- __frexp_result_abstract
+ Enable(ast::Extension::kF16);
+ auto* call = Call("frexp", 1_a);
+ WrapInFunction(Decl(Var("v", Call("frexp", 1_h))), //
+ Assign("v", call));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::F16>());
+ ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<sem::I32>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::AbstractFloat>());
+ ASSERT_TRUE(abstract_str->Members()[1]->Type()->Is<sem::AbstractInt>());
+}
+
+TEST_F(MaterializeAbstractStructure, Frexp_Vector_ExplicitType) {
+ // var v = frexp(vec2(1_h)); // v is __frexp_result_vec2_f16
+ // v = frexp(vec2(1)); // __frexp_result_vec2_f16 <- __frexp_result_vec2_abstract
+ Enable(ast::Extension::kF16);
+ auto* call = Call("frexp", Construct(ty.vec2(nullptr), 1_a));
+ WrapInFunction(Decl(Var("v", Call("frexp", Construct(ty.vec2(nullptr), 1_h)))),
+ Assign("v", call));
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ auto* sem = Sem().Get(call);
+ ASSERT_TRUE(sem->Is<sem::Materialize>());
+ auto* materialize = sem->As<sem::Materialize>();
+ ASSERT_TRUE(materialize->Type()->Is<sem::Struct>());
+ auto* concrete_str = materialize->Type()->As<sem::Struct>();
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(concrete_str->Members()[1]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(concrete_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::F16>());
+ ASSERT_TRUE(concrete_str->Members()[1]->Type()->As<sem::Vector>()->type()->Is<sem::I32>());
+ ASSERT_TRUE(materialize->Expr()->Type()->Is<sem::Struct>());
+ auto* abstract_str = materialize->Expr()->Type()->As<sem::Struct>();
+ ASSERT_TRUE(abstract_str->Members()[0]->Type()->Is<sem::Vector>());
+ ASSERT_TRUE(
+ abstract_str->Members()[0]->Type()->As<sem::Vector>()->type()->Is<sem::AbstractFloat>());
+ ASSERT_TRUE(
+ abstract_str->Members()[1]->Type()->As<sem::Vector>()->type()->Is<sem::AbstractInt>());
+}
+
+} // namespace materialize_abstract_structure
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 143334e..0fdd78c 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1726,6 +1726,12 @@
return Array(source, source, el_ty, a->Count(), /* explicit_stride */ 0);
}
return nullptr;
+ },
+ [&](const sem::Struct* s) -> const sem::Type* {
+ if (auto& tys = s->ConcreteTypes(); !tys.IsEmpty()) {
+ return target_ty ? target_ty : tys[0];
+ }
+ return nullptr;
});
}
@@ -1938,8 +1944,8 @@
bool has_side_effects =
std::any_of(args.begin(), args.end(), [](auto* e) { return e->HasSideEffects(); });
- // ct_init_or_conv is a helper for building either a sem::TypeInitializer or sem::TypeConversion
- // call for a InitConvIntrinsic with an optional template argument type.
+ // ct_init_or_conv is a helper for building either a sem::TypeInitializer or
+ // sem::TypeConversion call for a InitConvIntrinsic with an optional template argument type.
auto ct_init_or_conv = [&](InitConvIntrinsic ty, const sem::Type* template_arg) -> sem::Call* {
auto arg_tys = utils::Transform(args, [](auto* arg) { return arg->Type(); });
auto ctor_or_conv =
@@ -1987,8 +1993,8 @@
if (!value) {
// Constant evaluation failed.
// Can happen for expressions that will fail validation (later).
- // Use the kRuntime EvaluationStage, as kConstant will trigger an assertion in the
- // sem::Expression initializer, which checks that kConstant is paired with a
+ // Use the kRuntime EvaluationStage, as kConstant will trigger an assertion in
+ // the sem::Expression initializer, which checks that kConstant is paired with a
// constant value.
stage = sem::EvaluationStage::kRuntime;
}
@@ -1998,8 +2004,8 @@
current_statement_, value, has_side_effects);
};
- // ty_init_or_conv is a helper for building either a sem::TypeInitializer or sem::TypeConversion
- // call for the given semantic type.
+ // ty_init_or_conv is a helper for building either a sem::TypeInitializer or
+ // sem::TypeConversion call for the given semantic type.
auto ty_init_or_conv = [&](const sem::Type* ty) {
return Switch(
ty, //
@@ -2076,7 +2082,8 @@
});
};
- // ast::CallExpression has a target which is either an ast::Type or an ast::IdentifierExpression
+ // ast::CallExpression has a target which is either an ast::Type or an
+ // ast::IdentifierExpression
sem::Call* call = nullptr;
if (expr->target.type) {
// ast::CallExpression has an ast::Type as the target.
@@ -2188,7 +2195,8 @@
});
} else {
// ast::CallExpression has an ast::IdentifierExpression as the target.
- // This call is either a function call, builtin call, type initializer or type conversion.
+ // This call is either a function call, builtin call, type initializer or type
+ // conversion.
auto* ident = expr->target.name;
Mark(ident);
auto* resolved = sem_.ResolvedSymbol(ident);
@@ -2197,8 +2205,8 @@
[&](sem::Type* ty) {
// A type initializer or conversions.
// Note: Unlike the code path where we're resolving the call target from an
- // ast::Type, all types must already have the element type explicitly specified, so
- // there's no need to infer element types.
+ // ast::Type, all types must already have the element type explicitly specified,
+ // so there's no need to infer element types.
return ty_init_or_conv(ty);
},
[&](sem::Function* func) { return FunctionCall(expr, func, args, arg_behaviors); },
@@ -2264,7 +2272,8 @@
AddWarning("use of deprecated builtin", expr->source);
}
- // If the builtin is @const, and all arguments have constant values, evaluate the builtin now.
+ // If the builtin is @const, and all arguments have constant values, evaluate the builtin
+ // now.
auto stage = sem::EarliestStage(arg_stage, builtin.sem->Stage());
const sem::Constant* value = nullptr;
if (stage == sem::EvaluationStage::kConstant) {
@@ -2472,7 +2481,7 @@
if (loop_block->FirstContinue()) {
// If our identifier is in loop_block->decls, make sure its index is
// less than first_continue
- if (auto* decl = loop_block->Decls().Find(symbol)) {
+ if (auto decl = loop_block->Decls().Find(symbol)) {
if (decl->order >= loop_block->NumDeclsAtFirstContinue()) {
AddError("continue statement bypasses declaration of '" +
builder_->Symbols().NameFor(symbol) + "'",
@@ -2894,7 +2903,8 @@
}
}
- // Track the pipeline-overridable constants that are transitively referenced by this array type.
+ // Track the pipeline-overridable constants that are transitively referenced by this array
+ // type.
for (auto* var : transitively_referenced_overrides) {
out->AddTransitivelyReferencedOverride(var);
}
@@ -2955,8 +2965,9 @@
Mark(attr);
if (auto* sd = attr->As<ast::StrideAttribute>()) {
// If the element type is not plain, then el_ty->Align() may be 0, in which case we
- // could get a DBZ in ArrayStrideAttribute(). In this case, validation will error about
- // the invalid array element type (which is tested later), so this is just a seatbelt.
+ // could get a DBZ in ArrayStrideAttribute(). In this case, validation will error
+ // about the invalid array element type (which is tested later), so this is just a
+ // seatbelt.
if (IsPlain(el_ty)) {
explicit_stride = sd->stride;
if (!validator_.ArrayStrideAttribute(sd, el_ty->Size(), el_ty->Align())) {
diff --git a/src/tint/resolver/resolver_test_helper.h b/src/tint/resolver/resolver_test_helper.h
index 57fe14a..edbc456 100644
--- a/src/tint/resolver/resolver_test_helper.h
+++ b/src/tint/resolver/resolver_test_helper.h
@@ -151,6 +151,12 @@
using mat3x2 = mat<3, 2, T>;
template <typename T>
+using mat2x4 = mat<2, 4, T>;
+
+template <typename T>
+using mat4x2 = mat<4, 2, T>;
+
+template <typename T>
using mat3x3 = mat<3, 3, T>;
template <typename T>
@@ -235,12 +241,21 @@
using sem_type_func_ptr = const sem::Type* (*)(ProgramBuilder& b);
using type_name_func_ptr = std::string (*)();
+struct UnspecializedElementType {};
+
+/// Base template for DataType, specialized below.
template <typename T>
-struct DataType {};
+struct DataType {
+ /// The element type
+ using ElementType = UnspecializedElementType;
+};
/// Helper that represents no-type. Returns nullptr for all static methods.
template <>
struct DataType<void> {
+ /// The element type
+ using ElementType = void;
+
/// @return nullptr
static inline const ast::Type* AST(ProgramBuilder&) { return nullptr; }
/// @return nullptr
@@ -756,7 +771,13 @@
DataType<T>::Name};
}
-/// Base class for Value<T>
+/// True if DataType<T> is specialized for T, false otherwise.
+template <typename T>
+const bool IsDataTypeSpecializedFor =
+ !std::is_same_v<typename DataType<T>::ElementType, UnspecializedElementType>;
+
+namespace detail {
+/// ValueBase is a base class of ConcreteValue<T>
struct ValueBase {
/// Constructor
ValueBase() = default;
@@ -787,13 +808,12 @@
virtual std::ostream& Print(std::ostream& o) const = 0;
};
-/// Value<T> is an instance of a value of type DataType<T>. Useful for storing values to create
-/// expressions with.
+/// ConcreteValue<T> is used to create Values of type DataType<T> with a ScalarArgs initializer.
template <typename T>
-struct Value : ValueBase {
+struct ConcreteValue : ValueBase {
/// Constructor
- /// @param a the scalar args
- explicit Value(ScalarArgs a) : args(std::move(a)) {}
+ /// @param args the scalar args
+ explicit ConcreteValue(ScalarArgs args) : args_(std::move(args)) {}
/// Alias to T
using Type = T;
@@ -802,21 +822,16 @@
/// Alias to DataType::ElementType
using ElementType = typename DataType::ElementType;
- /// Creates a Value<T> with `args`
- /// @param args the args that will be passed to the expression
- /// @returns a Value<T>
- static Value Create(ScalarArgs args) { return Value{std::move(args)}; }
-
/// Creates an `ast::Expression` for the type T passing in previously stored args
/// @param b the ProgramBuilder
/// @returns an expression node
const ast::Expression* Expr(ProgramBuilder& b) const override {
auto create = CreatePtrsFor<T>();
- return (*create.expr)(b, args);
+ return (*create.expr)(b, args_);
}
/// @returns args used to create expression via `Expr`
- const ScalarArgs& Args() const override { return args; }
+ const ScalarArgs& Args() const override { return args_; }
/// @returns true if element type is abstract
bool IsAbstract() const override { return tint::IsAbstract<ElementType>; }
@@ -832,9 +847,9 @@
/// @returns input argument `o`
std::ostream& Print(std::ostream& o) const override {
o << TypeName() << "(";
- for (auto& a : args.values) {
+ for (auto& a : args_.values) {
o << std::get<ElementType>(a);
- if (&a != &args.values.Back()) {
+ if (&a != &args_.values.Back()) {
o << ", ";
}
}
@@ -842,60 +857,95 @@
return o;
}
+ private:
/// args to create expression with
- ScalarArgs args;
+ ScalarArgs args_;
};
-
-namespace detail {
-/// Base template for IsValue
-template <typename T>
-struct IsValue : std::false_type {};
-/// Specialization for IsValue
-template <typename T>
-struct IsValue<Value<T>> : std::true_type {};
} // namespace detail
-/// True if T is of type Value
-template <typename T>
-constexpr bool IsValue = detail::IsValue<T>::value;
+/// A Value represents a value of type DataType<T> created with ScalarArgs. Useful for storing
+/// values for unit tests.
+class Value {
+ public:
+ /// Creates a Value for type T initialized with `args`
+ /// @param args the scalar args
+ /// @returns Value
+ template <typename T>
+ static Value Create(ScalarArgs args) {
+ static_assert(IsDataTypeSpecializedFor<T>, "No DataType<T> specialization exists");
+ return Value{std::make_shared<detail::ConcreteValue<T>>(std::move(args))};
+ }
-/// Returns the friendly name of ValueT
-template <typename ValueT, typename = traits::EnableIf<IsValue<ValueT>>>
-const char* FriendlyName() {
- return tint::FriendlyName<typename ValueT::ElementType>();
+ /// Creates an `ast::Expression` for the type T passing in previously stored args
+ /// @param b the ProgramBuilder
+ /// @returns an expression node
+ const ast::Expression* Expr(ProgramBuilder& b) const { return value_->Expr(b); }
+
+ /// @returns args used to create expression via `Expr`
+ const ScalarArgs& Args() const { return value_->Args(); }
+
+ /// @returns true if element type is abstract
+ bool IsAbstract() const { return value_->IsAbstract(); }
+
+ /// @returns true if element type is an integral
+ bool IsIntegral() const { return value_->IsIntegral(); }
+
+ /// @returns element type name
+ std::string TypeName() const { return value_->TypeName(); }
+
+ /// Prints this value to the output stream
+ /// @param o the output stream
+ /// @returns input argument `o`
+ std::ostream& Print(std::ostream& o) const { return value_->Print(o); }
+
+ private:
+ /// Private constructor
+ explicit Value(std::shared_ptr<const detail::ValueBase> value) : value_(std::move(value)) {}
+
+ /// Shared pointer to an immutable value. This type-erasure pattern allows Value to wrap a
+ /// polymorphic type, while being used like a value-type (i.e. copyable).
+ std::shared_ptr<const detail::ValueBase> value_;
+};
+
+/// Prints Value to ostream
+inline std::ostream& operator<<(std::ostream& o, const Value& value) {
+ return value.Print(o);
}
-/// Creates a `Value<T>` from a scalar `v`
+/// True if T is Value, false otherwise
template <typename T>
-auto Val(T v) {
- return Value<T>::Create(ScalarArgs{v});
+constexpr bool IsValue = std::is_same_v<T, Value>;
+
+/// Creates a Value of DataType<T> from a scalar `v`
+template <typename T>
+Value Val(T v) {
+ return Value::Create<T>(ScalarArgs{v});
}
-/// Creates a `Value<vec<N, T>>` from N scalar `args`
+/// Creates a Value of DataType<vec<N, T>> from N scalar `args`
template <typename... T>
-auto Vec(T... args) {
- constexpr size_t N = sizeof...(args);
+Value Vec(T... args) {
using FirstT = std::tuple_element_t<0, std::tuple<T...>>;
+ constexpr size_t N = sizeof...(args);
utils::Vector v{args...};
- using VT = vec<N, FirstT>;
- return Value<VT>::Create(utils::VectorRef<FirstT>{v});
+ return Value::Create<vec<N, FirstT>>(utils::VectorRef<FirstT>{v});
}
-/// Creates a `Value<mat<C,R,T>` from C*R scalar `args`
+/// Creates a Value of DataType<mat<C,R,T> from C*R scalar `args`
template <size_t C, size_t R, typename T>
-auto Mat(const T (&m_in)[C][R]) {
+Value Mat(const T (&m_in)[C][R]) {
utils::Vector<T, C * R> m;
for (uint32_t i = 0; i < C; ++i) {
for (size_t j = 0; j < R; ++j) {
m.Push(m_in[i][j]);
}
}
- return Value<mat<C, R, T>>::Create(utils::VectorRef<T>{m});
+ return Value::Create<mat<C, R, T>>(utils::VectorRef<T>{m});
}
-/// Creates a `Value<mat<2,R,T>` from column vectors `c0` and `c1`
+/// Creates a Value of DataType<mat<2,R,T> from column vectors `c0` and `c1`
template <typename T, size_t R>
-auto Mat(const T (&c0)[R], const T (&c1)[R]) {
+Value Mat(const T (&c0)[R], const T (&c1)[R]) {
constexpr size_t C = 2;
utils::Vector<T, C * R> m;
for (auto v : c0) {
@@ -904,12 +954,12 @@
for (auto v : c1) {
m.Push(v);
}
- return Value<mat<C, R, T>>::Create(utils::VectorRef<T>{m});
+ return Value::Create<mat<C, R, T>>(utils::VectorRef<T>{m});
}
-/// Creates a `Value<mat<3,R,T>` from column vectors `c0`, `c1`, and `c2`
+/// Creates a Value of DataType<mat<3,R,T> from column vectors `c0`, `c1`, and `c2`
template <typename T, size_t R>
-auto Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R]) {
+Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R]) {
constexpr size_t C = 3;
utils::Vector<T, C * R> m;
for (auto v : c0) {
@@ -921,12 +971,12 @@
for (auto v : c2) {
m.Push(v);
}
- return Value<mat<C, R, T>>::Create(utils::VectorRef<T>{m});
+ return Value::Create<mat<C, R, T>>(utils::VectorRef<T>{m});
}
-/// Creates a `Value<mat<4,R,T>` from column vectors `c0`, `c1`, `c2`, and `c3`
+/// Creates a Value of DataType<mat<4,R,T> from column vectors `c0`, `c1`, `c2`, and `c3`
template <typename T, size_t R>
-auto Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R], const T (&c3)[R]) {
+Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R], const T (&c3)[R]) {
constexpr size_t C = 4;
utils::Vector<T, C * R> m;
for (auto v : c0) {
@@ -941,7 +991,7 @@
for (auto v : c3) {
m.Push(v);
}
- return Value<mat<C, R, T>>::Create(utils::VectorRef<T>{m});
+ return Value::Create<mat<C, R, T>>(utils::VectorRef<T>{m});
}
} // namespace builder
diff --git a/src/tint/resolver/sem_helper.h b/src/tint/resolver/sem_helper.h
index 12ef4a2..2e557d9 100644
--- a/src/tint/resolver/sem_helper.h
+++ b/src/tint/resolver/sem_helper.h
@@ -54,7 +54,7 @@
/// @param node the node to retrieve
template <typename SEM = sem::Node>
SEM* ResolvedSymbol(const ast::Node* node) const {
- auto* resolved = dependencies_.resolved_symbols.Find(node);
+ auto resolved = dependencies_.resolved_symbols.Find(node);
return resolved ? const_cast<SEM*>(builder_->Sem().Get<SEM>(*resolved)) : nullptr;
}
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index afdbdfb..ffedaf6 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -600,7 +600,7 @@
}
// Add an edge from the variable's loop input node to its value at this point.
- auto** in_node = info.var_in_nodes.Find(var);
+ auto in_node = info.var_in_nodes.Find(var);
TINT_ASSERT(Resolver, in_node != nullptr);
auto* out_node = current_function_->variables.Get(var);
if (out_node != *in_node) {
@@ -1334,7 +1334,7 @@
[&](const sem::Function* func) {
// We must have already analyzed the user-defined function since we process
// functions in dependency order.
- auto* info = functions_.Find(func->Declaration());
+ auto info = functions_.Find(func->Declaration());
TINT_ASSERT(Resolver, info != nullptr);
callsite_tag = info->callsite_tag;
function_tag = info->function_tag;
@@ -1466,7 +1466,7 @@
} else if (auto* user = target->As<sem::Function>()) {
// This is a call to a user-defined function, so inspect the functions called by that
// function and look for one whose node has an edge from the RequiredToBeUniform node.
- auto* target_info = functions_.Find(user->Declaration());
+ auto target_info = functions_.Find(user->Declaration());
for (auto* call_node : target_info->required_to_be_uniform->edges) {
if (call_node->type == Node::kRegular) {
auto* child_call = call_node->ast->As<ast::CallExpression>();
@@ -1636,7 +1636,7 @@
// If this is a call to a user-defined function, add a note to show the reason that the
// parameter is required to be uniform.
if (auto* user = target->As<sem::Function>()) {
- auto* next_function = functions_.Find(user->Declaration());
+ auto next_function = functions_.Find(user->Declaration());
Node* next_cause = next_function->parameters[cause->arg_index].init_value;
MakeError(*next_function, next_cause, true);
}
diff --git a/src/tint/resolver/validation_test.cc b/src/tint/resolver/validation_test.cc
index 2e41bf1..946bcb9 100644
--- a/src/tint/resolver/validation_test.cc
+++ b/src/tint/resolver/validation_test.cc
@@ -1298,6 +1298,23 @@
EXPECT_EQ(r()->error(), "12:24 error: value 4294967296 cannot be represented as 'u32'");
}
+// var a: array<i32,2>;
+// *&a[0] = 1;
+TEST_F(ResolverTest, PointerIndexing_Fail) {
+ // var a: array<i32,2>;
+ // let p = &a;
+ // *p[0] = 0;
+
+ auto* a = Var("a", ty.array<i32, 2>());
+ auto* p = AddressOf("a");
+ auto* idx = Assign(Deref(IndexAccessor(p, 0_u)), 0_u);
+
+ WrapInFunction(a, idx);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "error: cannot index type 'ptr<function, array<i32, 2>, read_write>'");
+}
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index db93bbe..70d9f8e 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -395,13 +395,11 @@
return true;
}
- // Temporally forbid using f16 types in "uniform" and "storage" address space.
- // TODO(tint:1473, tint:1502): Remove this error after f16 is supported in "uniform" and
- // "storage" address space but keep for "push_constant" address space.
- if (Is<sem::F16>(sem::Type::DeepestElementOf(store_ty))) {
- AddError("using f16 types in '" + utils::ToString(address_space) +
- "' address space is not implemented yet",
- source);
+ // Among three host-shareable address spaces, f16 is supported in "uniform" and
+ // "storage" address space, but not "push_constant" address space yet.
+ if (Is<sem::F16>(sem::Type::DeepestElementOf(store_ty)) &&
+ address_space == ast::AddressSpace::kPushConstant) {
+ AddError("using f16 types in 'push_constant' address space is not implemented yet", source);
return false;
}
@@ -719,7 +717,7 @@
return false;
}
} else if (type->IsAnyOf<sem::Struct, sem::Array>()) {
- if (auto* found = atomic_composite_info.Find(type)) {
+ if (auto found = atomic_composite_info.Find(type)) {
if (address_space != ast::AddressSpace::kStorage &&
address_space != ast::AddressSpace::kWorkgroup) {
AddError("atomic variables must have <storage> or <workgroup> address space",
@@ -798,7 +796,7 @@
for (auto* attr : decl->attributes) {
if (attr->Is<ast::IdAttribute>()) {
auto id = v->OverrideId();
- if (auto* var = override_ids.Find(id); var && *var != v) {
+ if (auto var = override_ids.Find(id); var && *var != v) {
AddError("@id values must be unique", attr->source);
AddNote(
"a override with an ID of " + std::to_string(id.value) +
diff --git a/src/tint/scope_stack.h b/src/tint/scope_stack.h
index a2da4dd..75c50b4 100644
--- a/src/tint/scope_stack.h
+++ b/src/tint/scope_stack.h
@@ -44,7 +44,7 @@
/// stack, otherwise the zero initializer for type T.
V Set(const K& key, V val) {
auto& back = stack_.Back();
- if (auto* el = back.Find(key)) {
+ if (auto el = back.Find(key)) {
std::swap(val, *el);
return val;
}
@@ -57,7 +57,7 @@
/// @returns the value, or the zero initializer if the value was not found
V Get(const K& key) const {
for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) {
- if (auto* val = iter->Find(key)) {
+ if (auto val = iter->Find(key)) {
return *val;
}
}
diff --git a/src/tint/sem/struct.h b/src/tint/sem/struct.h
index f35d5f4..0ddfa23 100644
--- a/src/tint/sem/struct.h
+++ b/src/tint/sem/struct.h
@@ -152,6 +152,14 @@
/// including size and alignment information.
std::string Layout(const tint::SymbolTable& symbols) const;
+ /// @param concrete the conversion-rank ordered concrete versions of this abstract structure.
+ void SetConcreteTypes(utils::VectorRef<const Struct*> concrete) { concrete_types_ = concrete; }
+
+ /// @returns the conversion-rank ordered concrete versions of this abstract structure, or an
+ /// empty vector if this structure is not abstract.
+ /// @note only structures returned by builtins may be abstract (e.g. modf, frexp)
+ const utils::Vector<const Struct*, 2>& ConcreteTypes() const { return concrete_types_; }
+
private:
ast::Struct const* const declaration_;
const Symbol name_;
@@ -161,6 +169,7 @@
const uint32_t size_no_padding_;
std::unordered_set<ast::AddressSpace> address_space_usage_;
std::unordered_set<PipelineStageUsage> pipeline_stage_uses_;
+ utils::Vector<const Struct*, 2> concrete_types_;
};
/// StructMember holds the semantic information for structure members.
diff --git a/src/tint/sem/type.cc b/src/tint/sem/type.cc
index 0596a37..f9db53b 100644
--- a/src/tint/sem/type.cc
+++ b/src/tint/sem/type.cc
@@ -238,6 +238,15 @@
}
return kNoConversion;
},
+ [&](const Struct* from_str) {
+ auto& concrete_tys = from_str->ConcreteTypes();
+ for (size_t i = 0; i < concrete_tys.Length(); i++) {
+ if (concrete_tys[i] == to) {
+ return static_cast<uint32_t>(i + 1);
+ }
+ }
+ return kNoConversion;
+ },
[&](Default) { return kNoConversion; });
}
diff --git a/src/tint/sem/type_test.cc b/src/tint/sem/type_test.cc
index ee79102..aec9bde 100644
--- a/src/tint/sem/type_test.cc
+++ b/src/tint/sem/type_test.cc
@@ -44,6 +44,22 @@
const sem::Matrix* mat4x3_af = create<Matrix>(vec3_af, 4u);
const sem::Reference* ref_u32 =
create<Reference>(u32, ast::AddressSpace::kPrivate, ast::Access::kReadWrite);
+ const sem::Struct* str_f32 = create<Struct>(nullptr,
+ Sym("str_f32"),
+ StructMemberList{
+ create<StructMember>(
+ /* declaration */ nullptr,
+ /* name */ Sym("x"),
+ /* type */ f32,
+ /* index */ 0u,
+ /* offset */ 0u,
+ /* align */ 4u,
+ /* size */ 4u,
+ /* location */ std::nullopt),
+ },
+ /* align*/ 4u,
+ /* size*/ 4u,
+ /* size_no_padding*/ 4u);
const sem::Struct* str_f16 = create<Struct>(nullptr,
Sym("str_f16"),
StructMemberList{
@@ -60,22 +76,22 @@
/* align*/ 4u,
/* size*/ 4u,
/* size_no_padding*/ 4u);
- const sem::Struct* str_af = create<Struct>(nullptr,
- Sym("str_af"),
- StructMemberList{
- create<StructMember>(
- /* declaration */ nullptr,
- /* name */ Sym("x"),
- /* type */ af,
- /* index */ 0u,
- /* offset */ 0u,
- /* align */ 4u,
- /* size */ 4u,
- /* location */ std::nullopt),
- },
- /* align*/ 4u,
- /* size*/ 4u,
- /* size_no_padding*/ 4u);
+ sem::Struct* str_af = create<Struct>(nullptr,
+ Sym("str_af"),
+ StructMemberList{
+ create<StructMember>(
+ /* declaration */ nullptr,
+ /* name */ Sym("x"),
+ /* type */ af,
+ /* index */ 0u,
+ /* offset */ 0u,
+ /* align */ 4u,
+ /* size */ 4u,
+ /* location */ std::nullopt),
+ },
+ /* align*/ 4u,
+ /* size*/ 4u,
+ /* size_no_padding*/ 4u);
const sem::Array* arr_i32 = create<Array>(
/* element */ i32,
/* count */ ConstantArrayCount{5u},
@@ -139,6 +155,8 @@
/* size */ 5u * 4u,
/* stride */ 5u * 4u,
/* implicit_stride */ 5u * 4u);
+
+ TypeTest() { str_af->SetConcreteTypes(utils::Vector{str_f32, str_f16}); }
};
TEST_F(TypeTest, ConversionRank) {
@@ -178,6 +196,8 @@
EXPECT_EQ(Type::ConversionRank(ai, af), 5u);
EXPECT_EQ(Type::ConversionRank(ai, f32), 6u);
EXPECT_EQ(Type::ConversionRank(ai, f16), 7u);
+ EXPECT_EQ(Type::ConversionRank(str_af, str_f32), 1u);
+ EXPECT_EQ(Type::ConversionRank(str_af, str_f16), 2u);
EXPECT_EQ(Type::ConversionRank(i32, f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f32, u32), Type::kNoConversion);
@@ -199,6 +219,10 @@
EXPECT_EQ(Type::ConversionRank(af, ai), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f32, ai), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f16, ai), Type::kNoConversion);
+ EXPECT_EQ(Type::ConversionRank(str_f32, str_f16), Type::kNoConversion);
+ EXPECT_EQ(Type::ConversionRank(str_f16, str_f32), Type::kNoConversion);
+ EXPECT_EQ(Type::ConversionRank(str_f32, str_af), Type::kNoConversion);
+ EXPECT_EQ(Type::ConversionRank(str_f16, str_af), Type::kNoConversion);
}
TEST_F(TypeTest, ElementOf) {
diff --git a/src/tint/transform/decompose_memory_access.cc b/src/tint/transform/decompose_memory_access.cc
index 046583e..3be550c 100644
--- a/src/tint/transform/decompose_memory_access.cc
+++ b/src/tint/transform/decompose_memory_access.cc
@@ -153,6 +153,10 @@
out = DecomposeMemoryAccess::Intrinsic::DataType::kF32;
return true;
}
+ if (ty->Is<sem::F16>()) {
+ out = DecomposeMemoryAccess::Intrinsic::DataType::kF16;
+ return true;
+ }
if (auto* vec = ty->As<sem::Vector>()) {
switch (vec->Width()) {
case 2:
@@ -168,6 +172,10 @@
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec2F32;
return true;
}
+ if (vec->type()->Is<sem::F16>()) {
+ out = DecomposeMemoryAccess::Intrinsic::DataType::kVec2F16;
+ return true;
+ }
break;
case 3:
if (vec->type()->Is<sem::I32>()) {
@@ -182,6 +190,10 @@
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec3F32;
return true;
}
+ if (vec->type()->Is<sem::F16>()) {
+ out = DecomposeMemoryAccess::Intrinsic::DataType::kVec3F16;
+ return true;
+ }
break;
case 4:
if (vec->type()->Is<sem::I32>()) {
@@ -196,6 +208,10 @@
out = DecomposeMemoryAccess::Intrinsic::DataType::kVec4F32;
return true;
}
+ if (vec->type()->Is<sem::F16>()) {
+ out = DecomposeMemoryAccess::Intrinsic::DataType::kVec4F16;
+ return true;
+ }
break;
}
return false;
@@ -776,6 +792,9 @@
case DataType::kI32:
ss << "i32";
break;
+ case DataType::kF16:
+ ss << "f16";
+ break;
case DataType::kVec2U32:
ss << "vec2_u32";
break;
@@ -785,6 +804,9 @@
case DataType::kVec2I32:
ss << "vec2_i32";
break;
+ case DataType::kVec2F16:
+ ss << "vec2_f16";
+ break;
case DataType::kVec3U32:
ss << "vec3_u32";
break;
@@ -794,6 +816,9 @@
case DataType::kVec3I32:
ss << "vec3_i32";
break;
+ case DataType::kVec3F16:
+ ss << "vec3_f16";
+ break;
case DataType::kVec4U32:
ss << "vec4_u32";
break;
@@ -803,6 +828,9 @@
case DataType::kVec4I32:
ss << "vec4_i32";
break;
+ case DataType::kVec4F16:
+ ss << "vec4_f16";
+ break;
}
return ss.str();
}
diff --git a/src/tint/transform/decompose_memory_access.h b/src/tint/transform/decompose_memory_access.h
index 21c196b..3c620e0 100644
--- a/src/tint/transform/decompose_memory_access.h
+++ b/src/tint/transform/decompose_memory_access.h
@@ -60,15 +60,19 @@
kU32,
kF32,
kI32,
+ kF16,
kVec2U32,
kVec2F32,
kVec2I32,
+ kVec2F16,
kVec3U32,
kVec3F32,
kVec3I32,
+ kVec3F16,
kVec4U32,
kVec4F32,
kVec4I32,
+ kVec4F16,
};
/// Constructor
diff --git a/src/tint/transform/decompose_memory_access_test.cc b/src/tint/transform/decompose_memory_access_test.cc
index 581731e..ac798e0 100644
--- a/src/tint/transform/decompose_memory_access_test.cc
+++ b/src/tint/transform/decompose_memory_access_test.cc
@@ -51,192 +51,308 @@
TEST_F(DecomposeMemoryAccessTest, SB_BasicLoad) {
auto* src = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_vec3_f16 : array<vec3<f16>, 2>,
};
@group(0) @binding(0) var<storage, read_write> sb : SB;
@compute @workgroup_size(1)
fn main() {
- var a : i32 = sb.a;
- var b : u32 = sb.b;
- var c : f32 = sb.c;
- var d : vec2<i32> = sb.d;
- var e : vec2<u32> = sb.e;
- var f : vec2<f32> = sb.f;
- var g : vec3<i32> = sb.g;
- var h : vec3<u32> = sb.h;
- var i : vec3<f32> = sb.i;
- var j : vec4<i32> = sb.j;
- var k : vec4<u32> = sb.k;
- var l : vec4<f32> = sb.l;
- var m : mat2x2<f32> = sb.m;
- var n : mat2x3<f32> = sb.n;
- var o : mat2x4<f32> = sb.o;
- var p : mat3x2<f32> = sb.p;
- var q : mat3x3<f32> = sb.q;
- var r : mat3x4<f32> = sb.r;
- var s : mat4x2<f32> = sb.s;
- var t : mat4x3<f32> = sb.t;
- var u : mat4x4<f32> = sb.u;
- var v : array<vec3<f32>, 2> = sb.v;
+ var scalar_f32 : f32 = sb.scalar_f32;
+ var scalar_i32 : i32 = sb.scalar_i32;
+ var scalar_u32 : u32 = sb.scalar_u32;
+ var scalar_f16 : f16 = sb.scalar_f16;
+ var vec2_f32 : vec2<f32> = sb.vec2_f32;
+ var vec2_i32 : vec2<i32> = sb.vec2_i32;
+ var vec2_u32 : vec2<u32> = sb.vec2_u32;
+ var vec2_f16 : vec2<f16> = sb.vec2_f16;
+ var vec3_f32 : vec3<f32> = sb.vec3_f32;
+ var vec3_i32 : vec3<i32> = sb.vec3_i32;
+ var vec3_u32 : vec3<u32> = sb.vec3_u32;
+ var vec3_f16 : vec3<f16> = sb.vec3_f16;
+ var vec4_f32 : vec4<f32> = sb.vec4_f32;
+ var vec4_i32 : vec4<i32> = sb.vec4_i32;
+ var vec4_u32 : vec4<u32> = sb.vec4_u32;
+ var vec4_f16 : vec4<f16> = sb.vec4_f16;
+ var mat2x2_f32 : mat2x2<f32> = sb.mat2x2_f32;
+ var mat2x3_f32 : mat2x3<f32> = sb.mat2x3_f32;
+ var mat2x4_f32 : mat2x4<f32> = sb.mat2x4_f32;
+ var mat3x2_f32 : mat3x2<f32> = sb.mat3x2_f32;
+ var mat3x3_f32 : mat3x3<f32> = sb.mat3x3_f32;
+ var mat3x4_f32 : mat3x4<f32> = sb.mat3x4_f32;
+ var mat4x2_f32 : mat4x2<f32> = sb.mat4x2_f32;
+ var mat4x3_f32 : mat4x3<f32> = sb.mat4x3_f32;
+ var mat4x4_f32 : mat4x4<f32> = sb.mat4x4_f32;
+ var mat2x2_f16 : mat2x2<f16> = sb.mat2x2_f16;
+ var mat2x3_f16 : mat2x3<f16> = sb.mat2x3_f16;
+ var mat2x4_f16 : mat2x4<f16> = sb.mat2x4_f16;
+ var mat3x2_f16 : mat3x2<f16> = sb.mat3x2_f16;
+ var mat3x3_f16 : mat3x3<f16> = sb.mat3x3_f16;
+ var mat3x4_f16 : mat3x4<f16> = sb.mat3x4_f16;
+ var mat4x2_f16 : mat4x2<f16> = sb.mat4x2_f16;
+ var mat4x3_f16 : mat4x3<f16> = sb.mat4x3_f16;
+ var mat4x4_f16 : mat4x4<f16> = sb.mat4x4_f16;
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = sb.arr2_vec3_f32;
+ var arr2_vec3_f16 : array<vec3<f16>, 2> = sb.arr2_vec3_f16;
}
)";
auto* expect = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_vec3_f16 : array<vec3<f16>, 2>,
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
+@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
+
@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
-@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
-
-@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
-
-@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f16
@internal(intrinsic_load_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
-@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
-@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+
+@internal(intrinsic_load_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f16>
@internal(intrinsic_load_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f32>
-@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
-@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+
+@internal(intrinsic_load_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f16>
@internal(intrinsic_load_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
- return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
+@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+
+@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+
+@internal(intrinsic_load_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f16>
+
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
+ return mat2x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)));
}
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
return mat2x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
- return mat2x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)));
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
+ return mat2x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)));
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
- return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
+ return mat3x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)));
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
return mat3x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)));
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
- return mat3x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)));
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
+ return mat3x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)));
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
- return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
+ return mat4x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)), tint_symbol_4(buffer, (offset + 24u)));
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
return mat4x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 48u)));
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
- return mat4x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)), tint_symbol_11(buffer, (offset + 48u)));
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
+ return mat4x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)), tint_symbol_12(buffer, (offset + 48u)));
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f16> {
+ return mat2x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)));
+}
+
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f16> {
+ return mat2x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f16> {
+ return mat2x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f16> {
+ return mat3x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f16> {
+ return mat3x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f16> {
+ return mat3x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f16> {
+ return mat4x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)), tint_symbol_7(buffer, (offset + 12u)));
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f16> {
+ return mat4x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f16> {
+ return mat4x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)), tint_symbol_15(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
var arr : array<vec3<f32>, 2u>;
- for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- arr[i_1] = tint_symbol_8(buffer, (offset + (i_1 * 16u)));
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ arr[i] = tint_symbol_8(buffer, (offset + (i * 16u)));
}
return arr;
}
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f16>, 2u> {
+ var arr_1 : array<vec3<f16>, 2u>;
+ for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
+ arr_1[i_1] = tint_symbol_11(buffer, (offset + (i_1 * 8u)));
+ }
+ return arr_1;
+}
+
@compute @workgroup_size(1)
fn main() {
- var a : i32 = tint_symbol(&(sb), 0u);
- var b : u32 = tint_symbol_1(&(sb), 4u);
- var c : f32 = tint_symbol_2(&(sb), 8u);
- var d : vec2<i32> = tint_symbol_3(&(sb), 16u);
- var e : vec2<u32> = tint_symbol_4(&(sb), 24u);
- var f : vec2<f32> = tint_symbol_5(&(sb), 32u);
- var g : vec3<i32> = tint_symbol_6(&(sb), 48u);
- var h : vec3<u32> = tint_symbol_7(&(sb), 64u);
- var i : vec3<f32> = tint_symbol_8(&(sb), 80u);
- var j : vec4<i32> = tint_symbol_9(&(sb), 96u);
- var k : vec4<u32> = tint_symbol_10(&(sb), 112u);
- var l : vec4<f32> = tint_symbol_11(&(sb), 128u);
- var m : mat2x2<f32> = tint_symbol_12(&(sb), 144u);
- var n : mat2x3<f32> = tint_symbol_13(&(sb), 160u);
- var o : mat2x4<f32> = tint_symbol_14(&(sb), 192u);
- var p : mat3x2<f32> = tint_symbol_15(&(sb), 224u);
- var q : mat3x3<f32> = tint_symbol_16(&(sb), 256u);
- var r : mat3x4<f32> = tint_symbol_17(&(sb), 304u);
- var s : mat4x2<f32> = tint_symbol_18(&(sb), 352u);
- var t : mat4x3<f32> = tint_symbol_19(&(sb), 384u);
- var u : mat4x4<f32> = tint_symbol_20(&(sb), 448u);
- var v : array<vec3<f32>, 2> = tint_symbol_21(&(sb), 512u);
+ var scalar_f32 : f32 = tint_symbol(&(sb), 0u);
+ var scalar_i32 : i32 = tint_symbol_1(&(sb), 4u);
+ var scalar_u32 : u32 = tint_symbol_2(&(sb), 8u);
+ var scalar_f16 : f16 = tint_symbol_3(&(sb), 12u);
+ var vec2_f32 : vec2<f32> = tint_symbol_4(&(sb), 16u);
+ var vec2_i32 : vec2<i32> = tint_symbol_5(&(sb), 24u);
+ var vec2_u32 : vec2<u32> = tint_symbol_6(&(sb), 32u);
+ var vec2_f16 : vec2<f16> = tint_symbol_7(&(sb), 40u);
+ var vec3_f32 : vec3<f32> = tint_symbol_8(&(sb), 48u);
+ var vec3_i32 : vec3<i32> = tint_symbol_9(&(sb), 64u);
+ var vec3_u32 : vec3<u32> = tint_symbol_10(&(sb), 80u);
+ var vec3_f16 : vec3<f16> = tint_symbol_11(&(sb), 96u);
+ var vec4_f32 : vec4<f32> = tint_symbol_12(&(sb), 112u);
+ var vec4_i32 : vec4<i32> = tint_symbol_13(&(sb), 128u);
+ var vec4_u32 : vec4<u32> = tint_symbol_14(&(sb), 144u);
+ var vec4_f16 : vec4<f16> = tint_symbol_15(&(sb), 160u);
+ var mat2x2_f32 : mat2x2<f32> = tint_symbol_16(&(sb), 168u);
+ var mat2x3_f32 : mat2x3<f32> = tint_symbol_17(&(sb), 192u);
+ var mat2x4_f32 : mat2x4<f32> = tint_symbol_18(&(sb), 224u);
+ var mat3x2_f32 : mat3x2<f32> = tint_symbol_19(&(sb), 256u);
+ var mat3x3_f32 : mat3x3<f32> = tint_symbol_20(&(sb), 288u);
+ var mat3x4_f32 : mat3x4<f32> = tint_symbol_21(&(sb), 336u);
+ var mat4x2_f32 : mat4x2<f32> = tint_symbol_22(&(sb), 384u);
+ var mat4x3_f32 : mat4x3<f32> = tint_symbol_23(&(sb), 416u);
+ var mat4x4_f32 : mat4x4<f32> = tint_symbol_24(&(sb), 480u);
+ var mat2x2_f16 : mat2x2<f16> = tint_symbol_25(&(sb), 544u);
+ var mat2x3_f16 : mat2x3<f16> = tint_symbol_26(&(sb), 552u);
+ var mat2x4_f16 : mat2x4<f16> = tint_symbol_27(&(sb), 568u);
+ var mat3x2_f16 : mat3x2<f16> = tint_symbol_28(&(sb), 584u);
+ var mat3x3_f16 : mat3x3<f16> = tint_symbol_29(&(sb), 600u);
+ var mat3x4_f16 : mat3x4<f16> = tint_symbol_30(&(sb), 624u);
+ var mat4x2_f16 : mat4x2<f16> = tint_symbol_31(&(sb), 648u);
+ var mat4x3_f16 : mat4x3<f16> = tint_symbol_32(&(sb), 664u);
+ var mat4x4_f16 : mat4x4<f16> = tint_symbol_33(&(sb), 696u);
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = tint_symbol_34(&(sb), 736u);
+ var arr2_vec3_f16 : array<vec3<f16>, 2> = tint_symbol_35(&(sb), 768u);
}
)";
@@ -247,192 +363,308 @@
TEST_F(DecomposeMemoryAccessTest, SB_BasicLoad_OutOfOrder) {
auto* src = R"(
+enable f16;
+
@compute @workgroup_size(1)
fn main() {
- var a : i32 = sb.a;
- var b : u32 = sb.b;
- var c : f32 = sb.c;
- var d : vec2<i32> = sb.d;
- var e : vec2<u32> = sb.e;
- var f : vec2<f32> = sb.f;
- var g : vec3<i32> = sb.g;
- var h : vec3<u32> = sb.h;
- var i : vec3<f32> = sb.i;
- var j : vec4<i32> = sb.j;
- var k : vec4<u32> = sb.k;
- var l : vec4<f32> = sb.l;
- var m : mat2x2<f32> = sb.m;
- var n : mat2x3<f32> = sb.n;
- var o : mat2x4<f32> = sb.o;
- var p : mat3x2<f32> = sb.p;
- var q : mat3x3<f32> = sb.q;
- var r : mat3x4<f32> = sb.r;
- var s : mat4x2<f32> = sb.s;
- var t : mat4x3<f32> = sb.t;
- var u : mat4x4<f32> = sb.u;
- var v : array<vec3<f32>, 2> = sb.v;
+ var scalar_f32 : f32 = sb.scalar_f32;
+ var scalar_i32 : i32 = sb.scalar_i32;
+ var scalar_u32 : u32 = sb.scalar_u32;
+ var scalar_f16 : f16 = sb.scalar_f16;
+ var vec2_f32 : vec2<f32> = sb.vec2_f32;
+ var vec2_i32 : vec2<i32> = sb.vec2_i32;
+ var vec2_u32 : vec2<u32> = sb.vec2_u32;
+ var vec2_f16 : vec2<f16> = sb.vec2_f16;
+ var vec3_f32 : vec3<f32> = sb.vec3_f32;
+ var vec3_i32 : vec3<i32> = sb.vec3_i32;
+ var vec3_u32 : vec3<u32> = sb.vec3_u32;
+ var vec3_f16 : vec3<f16> = sb.vec3_f16;
+ var vec4_f32 : vec4<f32> = sb.vec4_f32;
+ var vec4_i32 : vec4<i32> = sb.vec4_i32;
+ var vec4_u32 : vec4<u32> = sb.vec4_u32;
+ var vec4_f16 : vec4<f16> = sb.vec4_f16;
+ var mat2x2_f32 : mat2x2<f32> = sb.mat2x2_f32;
+ var mat2x3_f32 : mat2x3<f32> = sb.mat2x3_f32;
+ var mat2x4_f32 : mat2x4<f32> = sb.mat2x4_f32;
+ var mat3x2_f32 : mat3x2<f32> = sb.mat3x2_f32;
+ var mat3x3_f32 : mat3x3<f32> = sb.mat3x3_f32;
+ var mat3x4_f32 : mat3x4<f32> = sb.mat3x4_f32;
+ var mat4x2_f32 : mat4x2<f32> = sb.mat4x2_f32;
+ var mat4x3_f32 : mat4x3<f32> = sb.mat4x3_f32;
+ var mat4x4_f32 : mat4x4<f32> = sb.mat4x4_f32;
+ var mat2x2_f16 : mat2x2<f16> = sb.mat2x2_f16;
+ var mat2x3_f16 : mat2x3<f16> = sb.mat2x3_f16;
+ var mat2x4_f16 : mat2x4<f16> = sb.mat2x4_f16;
+ var mat3x2_f16 : mat3x2<f16> = sb.mat3x2_f16;
+ var mat3x3_f16 : mat3x3<f16> = sb.mat3x3_f16;
+ var mat3x4_f16 : mat3x4<f16> = sb.mat3x4_f16;
+ var mat4x2_f16 : mat4x2<f16> = sb.mat4x2_f16;
+ var mat4x3_f16 : mat4x3<f16> = sb.mat4x3_f16;
+ var mat4x4_f16 : mat4x4<f16> = sb.mat4x4_f16;
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = sb.arr2_vec3_f32;
+ var arr2_vec3_f16 : array<vec3<f16>, 2> = sb.arr2_vec3_f16;
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_vec3_f16 : array<vec3<f16>, 2>,
};
)";
auto* expect = R"(
-@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
-
-@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
+enable f16;
@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
+fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
-@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
+@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
-@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
+
+@internal(intrinsic_load_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f16
@internal(intrinsic_load_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
-@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
-@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+
+@internal(intrinsic_load_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f16>
@internal(intrinsic_load_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f32>
-@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
-@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+
+@internal(intrinsic_load_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f16>
@internal(intrinsic_load_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
- return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
+@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+
+@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+
+@internal(intrinsic_load_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f16>
+
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
+ return mat2x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)));
}
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
return mat2x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
- return mat2x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)));
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
+ return mat2x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)));
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
- return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
+ return mat3x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)));
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
return mat3x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)));
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
- return mat3x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)));
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
+ return mat3x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)));
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
- return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
+ return mat4x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)), tint_symbol_4(buffer, (offset + 24u)));
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
return mat4x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 48u)));
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
- return mat4x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)), tint_symbol_11(buffer, (offset + 48u)));
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
+ return mat4x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)), tint_symbol_12(buffer, (offset + 48u)));
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f16> {
+ return mat2x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)));
+}
+
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f16> {
+ return mat2x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f16> {
+ return mat2x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f16> {
+ return mat3x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f16> {
+ return mat3x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f16> {
+ return mat3x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f16> {
+ return mat4x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)), tint_symbol_7(buffer, (offset + 12u)));
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f16> {
+ return mat4x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f16> {
+ return mat4x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)), tint_symbol_15(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
var arr : array<vec3<f32>, 2u>;
- for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- arr[i_1] = tint_symbol_8(buffer, (offset + (i_1 * 16u)));
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ arr[i] = tint_symbol_8(buffer, (offset + (i * 16u)));
}
return arr;
}
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f16>, 2u> {
+ var arr_1 : array<vec3<f16>, 2u>;
+ for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
+ arr_1[i_1] = tint_symbol_11(buffer, (offset + (i_1 * 8u)));
+ }
+ return arr_1;
+}
+
@compute @workgroup_size(1)
fn main() {
- var a : i32 = tint_symbol(&(sb), 0u);
- var b : u32 = tint_symbol_1(&(sb), 4u);
- var c : f32 = tint_symbol_2(&(sb), 8u);
- var d : vec2<i32> = tint_symbol_3(&(sb), 16u);
- var e : vec2<u32> = tint_symbol_4(&(sb), 24u);
- var f : vec2<f32> = tint_symbol_5(&(sb), 32u);
- var g : vec3<i32> = tint_symbol_6(&(sb), 48u);
- var h : vec3<u32> = tint_symbol_7(&(sb), 64u);
- var i : vec3<f32> = tint_symbol_8(&(sb), 80u);
- var j : vec4<i32> = tint_symbol_9(&(sb), 96u);
- var k : vec4<u32> = tint_symbol_10(&(sb), 112u);
- var l : vec4<f32> = tint_symbol_11(&(sb), 128u);
- var m : mat2x2<f32> = tint_symbol_12(&(sb), 144u);
- var n : mat2x3<f32> = tint_symbol_13(&(sb), 160u);
- var o : mat2x4<f32> = tint_symbol_14(&(sb), 192u);
- var p : mat3x2<f32> = tint_symbol_15(&(sb), 224u);
- var q : mat3x3<f32> = tint_symbol_16(&(sb), 256u);
- var r : mat3x4<f32> = tint_symbol_17(&(sb), 304u);
- var s : mat4x2<f32> = tint_symbol_18(&(sb), 352u);
- var t : mat4x3<f32> = tint_symbol_19(&(sb), 384u);
- var u : mat4x4<f32> = tint_symbol_20(&(sb), 448u);
- var v : array<vec3<f32>, 2> = tint_symbol_21(&(sb), 512u);
+ var scalar_f32 : f32 = tint_symbol(&(sb), 0u);
+ var scalar_i32 : i32 = tint_symbol_1(&(sb), 4u);
+ var scalar_u32 : u32 = tint_symbol_2(&(sb), 8u);
+ var scalar_f16 : f16 = tint_symbol_3(&(sb), 12u);
+ var vec2_f32 : vec2<f32> = tint_symbol_4(&(sb), 16u);
+ var vec2_i32 : vec2<i32> = tint_symbol_5(&(sb), 24u);
+ var vec2_u32 : vec2<u32> = tint_symbol_6(&(sb), 32u);
+ var vec2_f16 : vec2<f16> = tint_symbol_7(&(sb), 40u);
+ var vec3_f32 : vec3<f32> = tint_symbol_8(&(sb), 48u);
+ var vec3_i32 : vec3<i32> = tint_symbol_9(&(sb), 64u);
+ var vec3_u32 : vec3<u32> = tint_symbol_10(&(sb), 80u);
+ var vec3_f16 : vec3<f16> = tint_symbol_11(&(sb), 96u);
+ var vec4_f32 : vec4<f32> = tint_symbol_12(&(sb), 112u);
+ var vec4_i32 : vec4<i32> = tint_symbol_13(&(sb), 128u);
+ var vec4_u32 : vec4<u32> = tint_symbol_14(&(sb), 144u);
+ var vec4_f16 : vec4<f16> = tint_symbol_15(&(sb), 160u);
+ var mat2x2_f32 : mat2x2<f32> = tint_symbol_16(&(sb), 168u);
+ var mat2x3_f32 : mat2x3<f32> = tint_symbol_17(&(sb), 192u);
+ var mat2x4_f32 : mat2x4<f32> = tint_symbol_18(&(sb), 224u);
+ var mat3x2_f32 : mat3x2<f32> = tint_symbol_19(&(sb), 256u);
+ var mat3x3_f32 : mat3x3<f32> = tint_symbol_20(&(sb), 288u);
+ var mat3x4_f32 : mat3x4<f32> = tint_symbol_21(&(sb), 336u);
+ var mat4x2_f32 : mat4x2<f32> = tint_symbol_22(&(sb), 384u);
+ var mat4x3_f32 : mat4x3<f32> = tint_symbol_23(&(sb), 416u);
+ var mat4x4_f32 : mat4x4<f32> = tint_symbol_24(&(sb), 480u);
+ var mat2x2_f16 : mat2x2<f16> = tint_symbol_25(&(sb), 544u);
+ var mat2x3_f16 : mat2x3<f16> = tint_symbol_26(&(sb), 552u);
+ var mat2x4_f16 : mat2x4<f16> = tint_symbol_27(&(sb), 568u);
+ var mat3x2_f16 : mat3x2<f16> = tint_symbol_28(&(sb), 584u);
+ var mat3x3_f16 : mat3x3<f16> = tint_symbol_29(&(sb), 600u);
+ var mat3x4_f16 : mat3x4<f16> = tint_symbol_30(&(sb), 624u);
+ var mat4x2_f16 : mat4x2<f16> = tint_symbol_31(&(sb), 648u);
+ var mat4x3_f16 : mat4x3<f16> = tint_symbol_32(&(sb), 664u);
+ var mat4x4_f16 : mat4x4<f16> = tint_symbol_33(&(sb), 696u);
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = tint_symbol_34(&(sb), 736u);
+ var arr2_vec3_f16 : array<vec3<f16>, 2> = tint_symbol_35(&(sb), 768u);
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_vec3_f16 : array<vec3<f16>, 2>,
}
)";
@@ -443,192 +675,308 @@
TEST_F(DecomposeMemoryAccessTest, UB_BasicLoad) {
auto* src = R"(
+enable f16;
+
struct UB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
@group(0) @binding(0) var<uniform> ub : UB;
@compute @workgroup_size(1)
fn main() {
- var a : i32 = ub.a;
- var b : u32 = ub.b;
- var c : f32 = ub.c;
- var d : vec2<i32> = ub.d;
- var e : vec2<u32> = ub.e;
- var f : vec2<f32> = ub.f;
- var g : vec3<i32> = ub.g;
- var h : vec3<u32> = ub.h;
- var i : vec3<f32> = ub.i;
- var j : vec4<i32> = ub.j;
- var k : vec4<u32> = ub.k;
- var l : vec4<f32> = ub.l;
- var m : mat2x2<f32> = ub.m;
- var n : mat2x3<f32> = ub.n;
- var o : mat2x4<f32> = ub.o;
- var p : mat3x2<f32> = ub.p;
- var q : mat3x3<f32> = ub.q;
- var r : mat3x4<f32> = ub.r;
- var s : mat4x2<f32> = ub.s;
- var t : mat4x3<f32> = ub.t;
- var u : mat4x4<f32> = ub.u;
- var v : array<vec3<f32>, 2> = ub.v;
+ var scalar_f32 : f32 = ub.scalar_f32;
+ var scalar_i32 : i32 = ub.scalar_i32;
+ var scalar_u32 : u32 = ub.scalar_u32;
+ var scalar_f16 : f16 = ub.scalar_f16;
+ var vec2_f32 : vec2<f32> = ub.vec2_f32;
+ var vec2_i32 : vec2<i32> = ub.vec2_i32;
+ var vec2_u32 : vec2<u32> = ub.vec2_u32;
+ var vec2_f16 : vec2<f16> = ub.vec2_f16;
+ var vec3_f32 : vec3<f32> = ub.vec3_f32;
+ var vec3_i32 : vec3<i32> = ub.vec3_i32;
+ var vec3_u32 : vec3<u32> = ub.vec3_u32;
+ var vec3_f16 : vec3<f16> = ub.vec3_f16;
+ var vec4_f32 : vec4<f32> = ub.vec4_f32;
+ var vec4_i32 : vec4<i32> = ub.vec4_i32;
+ var vec4_u32 : vec4<u32> = ub.vec4_u32;
+ var vec4_f16 : vec4<f16> = ub.vec4_f16;
+ var mat2x2_f32 : mat2x2<f32> = ub.mat2x2_f32;
+ var mat2x3_f32 : mat2x3<f32> = ub.mat2x3_f32;
+ var mat2x4_f32 : mat2x4<f32> = ub.mat2x4_f32;
+ var mat3x2_f32 : mat3x2<f32> = ub.mat3x2_f32;
+ var mat3x3_f32 : mat3x3<f32> = ub.mat3x3_f32;
+ var mat3x4_f32 : mat3x4<f32> = ub.mat3x4_f32;
+ var mat4x2_f32 : mat4x2<f32> = ub.mat4x2_f32;
+ var mat4x3_f32 : mat4x3<f32> = ub.mat4x3_f32;
+ var mat4x4_f32 : mat4x4<f32> = ub.mat4x4_f32;
+ var mat2x2_f16 : mat2x2<f16> = ub.mat2x2_f16;
+ var mat2x3_f16 : mat2x3<f16> = ub.mat2x3_f16;
+ var mat2x4_f16 : mat2x4<f16> = ub.mat2x4_f16;
+ var mat3x2_f16 : mat3x2<f16> = ub.mat3x2_f16;
+ var mat3x3_f16 : mat3x3<f16> = ub.mat3x3_f16;
+ var mat3x4_f16 : mat3x4<f16> = ub.mat3x4_f16;
+ var mat4x2_f16 : mat4x2<f16> = ub.mat4x2_f16;
+ var mat4x3_f16 : mat4x3<f16> = ub.mat4x3_f16;
+ var mat4x4_f16 : mat4x4<f16> = ub.mat4x4_f16;
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = ub.arr2_vec3_f32;
+ var arr2_mat4x2_f16 : array<mat4x2<f16>, 2> = ub.arr2_mat4x2_f16;
}
)";
auto* expect = R"(
+enable f16;
+
struct UB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
@group(0) @binding(0) var<uniform> ub : UB;
+@internal(intrinsic_load_uniform_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> f32
+
@internal(intrinsic_load_uniform_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> i32
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> i32
@internal(intrinsic_load_uniform_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> u32
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> u32
-@internal(intrinsic_load_uniform_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> f32
-
-@internal(intrinsic_load_uniform_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<i32>
-
-@internal(intrinsic_load_uniform_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_uniform_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> f16
@internal(intrinsic_load_uniform_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<f32>
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<f32>
-@internal(intrinsic_load_uniform_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_uniform_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<i32>
-@internal(intrinsic_load_uniform_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_uniform_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<u32>
+
+@internal(intrinsic_load_uniform_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<f16>
@internal(intrinsic_load_uniform_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<f32>
-@internal(intrinsic_load_uniform_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_uniform_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<i32>
-@internal(intrinsic_load_uniform_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_uniform_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<u32>
+
+@internal(intrinsic_load_uniform_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<f16>
@internal(intrinsic_load_uniform_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<f32>
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<f32>
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x2<f32> {
- return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
+@internal(intrinsic_load_uniform_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<i32>
+
+@internal(intrinsic_load_uniform_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<u32>
+
+@internal(intrinsic_load_uniform_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<f16>
+
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x2<f32> {
+ return mat2x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)));
}
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x3<f32> {
return mat2x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x4<f32> {
- return mat2x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)));
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x4<f32> {
+ return mat2x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)));
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x2<f32> {
- return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x2<f32> {
+ return mat3x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)));
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x3<f32> {
return mat3x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)));
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x4<f32> {
- return mat3x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)));
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x4<f32> {
+ return mat3x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)));
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x2<f32> {
- return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x2<f32> {
+ return mat4x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)), tint_symbol_4(buffer, (offset + 24u)));
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x3<f32> {
return mat4x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 48u)));
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x4<f32> {
- return mat4x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)), tint_symbol_11(buffer, (offset + 48u)));
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x4<f32> {
+ return mat4x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)), tint_symbol_12(buffer, (offset + 48u)));
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x2<f16> {
+ return mat2x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)));
+}
+
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x3<f16> {
+ return mat2x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x4<f16> {
+ return mat2x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x2<f16> {
+ return mat3x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x3<f16> {
+ return mat3x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x4<f16> {
+ return mat3x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x2<f16> {
+ return mat4x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)), tint_symbol_7(buffer, (offset + 12u)));
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x3<f16> {
+ return mat4x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x4<f16> {
+ return mat4x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)), tint_symbol_15(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> array<vec3<f32>, 2u> {
var arr : array<vec3<f32>, 2u>;
- for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- arr[i_1] = tint_symbol_8(buffer, (offset + (i_1 * 16u)));
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ arr[i] = tint_symbol_8(buffer, (offset + (i * 16u)));
}
return arr;
}
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> array<mat4x2<f16>, 2u> {
+ var arr_1 : array<mat4x2<f16>, 2u>;
+ for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
+ arr_1[i_1] = tint_symbol_31(buffer, (offset + (i_1 * 16u)));
+ }
+ return arr_1;
+}
+
@compute @workgroup_size(1)
fn main() {
- var a : i32 = tint_symbol(&(ub), 0u);
- var b : u32 = tint_symbol_1(&(ub), 4u);
- var c : f32 = tint_symbol_2(&(ub), 8u);
- var d : vec2<i32> = tint_symbol_3(&(ub), 16u);
- var e : vec2<u32> = tint_symbol_4(&(ub), 24u);
- var f : vec2<f32> = tint_symbol_5(&(ub), 32u);
- var g : vec3<i32> = tint_symbol_6(&(ub), 48u);
- var h : vec3<u32> = tint_symbol_7(&(ub), 64u);
- var i : vec3<f32> = tint_symbol_8(&(ub), 80u);
- var j : vec4<i32> = tint_symbol_9(&(ub), 96u);
- var k : vec4<u32> = tint_symbol_10(&(ub), 112u);
- var l : vec4<f32> = tint_symbol_11(&(ub), 128u);
- var m : mat2x2<f32> = tint_symbol_12(&(ub), 144u);
- var n : mat2x3<f32> = tint_symbol_13(&(ub), 160u);
- var o : mat2x4<f32> = tint_symbol_14(&(ub), 192u);
- var p : mat3x2<f32> = tint_symbol_15(&(ub), 224u);
- var q : mat3x3<f32> = tint_symbol_16(&(ub), 256u);
- var r : mat3x4<f32> = tint_symbol_17(&(ub), 304u);
- var s : mat4x2<f32> = tint_symbol_18(&(ub), 352u);
- var t : mat4x3<f32> = tint_symbol_19(&(ub), 384u);
- var u : mat4x4<f32> = tint_symbol_20(&(ub), 448u);
- var v : array<vec3<f32>, 2> = tint_symbol_21(&(ub), 512u);
+ var scalar_f32 : f32 = tint_symbol(&(ub), 0u);
+ var scalar_i32 : i32 = tint_symbol_1(&(ub), 4u);
+ var scalar_u32 : u32 = tint_symbol_2(&(ub), 8u);
+ var scalar_f16 : f16 = tint_symbol_3(&(ub), 12u);
+ var vec2_f32 : vec2<f32> = tint_symbol_4(&(ub), 16u);
+ var vec2_i32 : vec2<i32> = tint_symbol_5(&(ub), 24u);
+ var vec2_u32 : vec2<u32> = tint_symbol_6(&(ub), 32u);
+ var vec2_f16 : vec2<f16> = tint_symbol_7(&(ub), 40u);
+ var vec3_f32 : vec3<f32> = tint_symbol_8(&(ub), 48u);
+ var vec3_i32 : vec3<i32> = tint_symbol_9(&(ub), 64u);
+ var vec3_u32 : vec3<u32> = tint_symbol_10(&(ub), 80u);
+ var vec3_f16 : vec3<f16> = tint_symbol_11(&(ub), 96u);
+ var vec4_f32 : vec4<f32> = tint_symbol_12(&(ub), 112u);
+ var vec4_i32 : vec4<i32> = tint_symbol_13(&(ub), 128u);
+ var vec4_u32 : vec4<u32> = tint_symbol_14(&(ub), 144u);
+ var vec4_f16 : vec4<f16> = tint_symbol_15(&(ub), 160u);
+ var mat2x2_f32 : mat2x2<f32> = tint_symbol_16(&(ub), 168u);
+ var mat2x3_f32 : mat2x3<f32> = tint_symbol_17(&(ub), 192u);
+ var mat2x4_f32 : mat2x4<f32> = tint_symbol_18(&(ub), 224u);
+ var mat3x2_f32 : mat3x2<f32> = tint_symbol_19(&(ub), 256u);
+ var mat3x3_f32 : mat3x3<f32> = tint_symbol_20(&(ub), 288u);
+ var mat3x4_f32 : mat3x4<f32> = tint_symbol_21(&(ub), 336u);
+ var mat4x2_f32 : mat4x2<f32> = tint_symbol_22(&(ub), 384u);
+ var mat4x3_f32 : mat4x3<f32> = tint_symbol_23(&(ub), 416u);
+ var mat4x4_f32 : mat4x4<f32> = tint_symbol_24(&(ub), 480u);
+ var mat2x2_f16 : mat2x2<f16> = tint_symbol_25(&(ub), 544u);
+ var mat2x3_f16 : mat2x3<f16> = tint_symbol_26(&(ub), 552u);
+ var mat2x4_f16 : mat2x4<f16> = tint_symbol_27(&(ub), 568u);
+ var mat3x2_f16 : mat3x2<f16> = tint_symbol_28(&(ub), 584u);
+ var mat3x3_f16 : mat3x3<f16> = tint_symbol_29(&(ub), 600u);
+ var mat3x4_f16 : mat3x4<f16> = tint_symbol_30(&(ub), 624u);
+ var mat4x2_f16 : mat4x2<f16> = tint_symbol_31(&(ub), 648u);
+ var mat4x3_f16 : mat4x3<f16> = tint_symbol_32(&(ub), 664u);
+ var mat4x4_f16 : mat4x4<f16> = tint_symbol_33(&(ub), 696u);
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = tint_symbol_34(&(ub), 736u);
+ var arr2_mat4x2_f16 : array<mat4x2<f16>, 2> = tint_symbol_35(&(ub), 768u);
}
)";
@@ -639,192 +987,308 @@
TEST_F(DecomposeMemoryAccessTest, UB_BasicLoad_OutOfOrder) {
auto* src = R"(
+enable f16;
+
@compute @workgroup_size(1)
fn main() {
- var a : i32 = ub.a;
- var b : u32 = ub.b;
- var c : f32 = ub.c;
- var d : vec2<i32> = ub.d;
- var e : vec2<u32> = ub.e;
- var f : vec2<f32> = ub.f;
- var g : vec3<i32> = ub.g;
- var h : vec3<u32> = ub.h;
- var i : vec3<f32> = ub.i;
- var j : vec4<i32> = ub.j;
- var k : vec4<u32> = ub.k;
- var l : vec4<f32> = ub.l;
- var m : mat2x2<f32> = ub.m;
- var n : mat2x3<f32> = ub.n;
- var o : mat2x4<f32> = ub.o;
- var p : mat3x2<f32> = ub.p;
- var q : mat3x3<f32> = ub.q;
- var r : mat3x4<f32> = ub.r;
- var s : mat4x2<f32> = ub.s;
- var t : mat4x3<f32> = ub.t;
- var u : mat4x4<f32> = ub.u;
- var v : array<vec3<f32>, 2> = ub.v;
+ var scalar_f32 : f32 = ub.scalar_f32;
+ var scalar_i32 : i32 = ub.scalar_i32;
+ var scalar_u32 : u32 = ub.scalar_u32;
+ var scalar_f16 : f16 = ub.scalar_f16;
+ var vec2_f32 : vec2<f32> = ub.vec2_f32;
+ var vec2_i32 : vec2<i32> = ub.vec2_i32;
+ var vec2_u32 : vec2<u32> = ub.vec2_u32;
+ var vec2_f16 : vec2<f16> = ub.vec2_f16;
+ var vec3_f32 : vec3<f32> = ub.vec3_f32;
+ var vec3_i32 : vec3<i32> = ub.vec3_i32;
+ var vec3_u32 : vec3<u32> = ub.vec3_u32;
+ var vec3_f16 : vec3<f16> = ub.vec3_f16;
+ var vec4_f32 : vec4<f32> = ub.vec4_f32;
+ var vec4_i32 : vec4<i32> = ub.vec4_i32;
+ var vec4_u32 : vec4<u32> = ub.vec4_u32;
+ var vec4_f16 : vec4<f16> = ub.vec4_f16;
+ var mat2x2_f32 : mat2x2<f32> = ub.mat2x2_f32;
+ var mat2x3_f32 : mat2x3<f32> = ub.mat2x3_f32;
+ var mat2x4_f32 : mat2x4<f32> = ub.mat2x4_f32;
+ var mat3x2_f32 : mat3x2<f32> = ub.mat3x2_f32;
+ var mat3x3_f32 : mat3x3<f32> = ub.mat3x3_f32;
+ var mat3x4_f32 : mat3x4<f32> = ub.mat3x4_f32;
+ var mat4x2_f32 : mat4x2<f32> = ub.mat4x2_f32;
+ var mat4x3_f32 : mat4x3<f32> = ub.mat4x3_f32;
+ var mat4x4_f32 : mat4x4<f32> = ub.mat4x4_f32;
+ var mat2x2_f16 : mat2x2<f16> = ub.mat2x2_f16;
+ var mat2x3_f16 : mat2x3<f16> = ub.mat2x3_f16;
+ var mat2x4_f16 : mat2x4<f16> = ub.mat2x4_f16;
+ var mat3x2_f16 : mat3x2<f16> = ub.mat3x2_f16;
+ var mat3x3_f16 : mat3x3<f16> = ub.mat3x3_f16;
+ var mat3x4_f16 : mat3x4<f16> = ub.mat3x4_f16;
+ var mat4x2_f16 : mat4x2<f16> = ub.mat4x2_f16;
+ var mat4x3_f16 : mat4x3<f16> = ub.mat4x3_f16;
+ var mat4x4_f16 : mat4x4<f16> = ub.mat4x4_f16;
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = ub.arr2_vec3_f32;
+ var arr2_mat4x2_f16 : array<mat4x2<f16>, 2> = ub.arr2_mat4x2_f16;
}
@group(0) @binding(0) var<uniform> ub : UB;
struct UB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
)";
auto* expect = R"(
-@internal(intrinsic_load_uniform_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> i32
-
-@internal(intrinsic_load_uniform_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> u32
+enable f16;
@internal(intrinsic_load_uniform_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> f32
+fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> f32
-@internal(intrinsic_load_uniform_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<i32>
+@internal(intrinsic_load_uniform_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> i32
-@internal(intrinsic_load_uniform_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_uniform_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> u32
+
+@internal(intrinsic_load_uniform_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> f16
@internal(intrinsic_load_uniform_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<f32>
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<f32>
-@internal(intrinsic_load_uniform_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_uniform_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<i32>
-@internal(intrinsic_load_uniform_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_uniform_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<u32>
+
+@internal(intrinsic_load_uniform_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec2<f16>
@internal(intrinsic_load_uniform_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<f32>
-@internal(intrinsic_load_uniform_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_uniform_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<i32>
-@internal(intrinsic_load_uniform_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_uniform_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<u32>
+
+@internal(intrinsic_load_uniform_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec3<f16>
@internal(intrinsic_load_uniform_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<f32>
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<f32>
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x2<f32> {
- return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
+@internal(intrinsic_load_uniform_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<i32>
+
+@internal(intrinsic_load_uniform_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<u32>
+
+@internal(intrinsic_load_uniform_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> vec4<f16>
+
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x2<f32> {
+ return mat2x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)));
}
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x3<f32> {
return mat2x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x4<f32> {
- return mat2x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)));
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x4<f32> {
+ return mat2x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)));
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x2<f32> {
- return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x2<f32> {
+ return mat3x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)));
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x3<f32> {
return mat3x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)));
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x4<f32> {
- return mat3x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)));
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x4<f32> {
+ return mat3x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)));
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x2<f32> {
- return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x2<f32> {
+ return mat4x2<f32>(tint_symbol_4(buffer, (offset + 0u)), tint_symbol_4(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)), tint_symbol_4(buffer, (offset + 24u)));
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x3<f32> {
return mat4x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 48u)));
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x4<f32> {
- return mat4x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)), tint_symbol_11(buffer, (offset + 48u)));
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x4<f32> {
+ return mat4x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)), tint_symbol_12(buffer, (offset + 48u)));
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x2<f16> {
+ return mat2x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)));
+}
+
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x3<f16> {
+ return mat2x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat2x4<f16> {
+ return mat2x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x2<f16> {
+ return mat3x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x3<f16> {
+ return mat3x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat3x4<f16> {
+ return mat3x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x2<f16> {
+ return mat4x2<f16>(tint_symbol_7(buffer, (offset + 0u)), tint_symbol_7(buffer, (offset + 4u)), tint_symbol_7(buffer, (offset + 8u)), tint_symbol_7(buffer, (offset + 12u)));
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x3<f16> {
+ return mat4x3<f16>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 8u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> mat4x4<f16> {
+ return mat4x4<f16>(tint_symbol_15(buffer, (offset + 0u)), tint_symbol_15(buffer, (offset + 8u)), tint_symbol_15(buffer, (offset + 16u)), tint_symbol_15(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> array<vec3<f32>, 2u> {
var arr : array<vec3<f32>, 2u>;
- for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- arr[i_1] = tint_symbol_8(buffer, (offset + (i_1 * 16u)));
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ arr[i] = tint_symbol_8(buffer, (offset + (i * 16u)));
}
return arr;
}
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<uniform, UB, read>, offset : u32) -> array<mat4x2<f16>, 2u> {
+ var arr_1 : array<mat4x2<f16>, 2u>;
+ for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
+ arr_1[i_1] = tint_symbol_31(buffer, (offset + (i_1 * 16u)));
+ }
+ return arr_1;
+}
+
@compute @workgroup_size(1)
fn main() {
- var a : i32 = tint_symbol(&(ub), 0u);
- var b : u32 = tint_symbol_1(&(ub), 4u);
- var c : f32 = tint_symbol_2(&(ub), 8u);
- var d : vec2<i32> = tint_symbol_3(&(ub), 16u);
- var e : vec2<u32> = tint_symbol_4(&(ub), 24u);
- var f : vec2<f32> = tint_symbol_5(&(ub), 32u);
- var g : vec3<i32> = tint_symbol_6(&(ub), 48u);
- var h : vec3<u32> = tint_symbol_7(&(ub), 64u);
- var i : vec3<f32> = tint_symbol_8(&(ub), 80u);
- var j : vec4<i32> = tint_symbol_9(&(ub), 96u);
- var k : vec4<u32> = tint_symbol_10(&(ub), 112u);
- var l : vec4<f32> = tint_symbol_11(&(ub), 128u);
- var m : mat2x2<f32> = tint_symbol_12(&(ub), 144u);
- var n : mat2x3<f32> = tint_symbol_13(&(ub), 160u);
- var o : mat2x4<f32> = tint_symbol_14(&(ub), 192u);
- var p : mat3x2<f32> = tint_symbol_15(&(ub), 224u);
- var q : mat3x3<f32> = tint_symbol_16(&(ub), 256u);
- var r : mat3x4<f32> = tint_symbol_17(&(ub), 304u);
- var s : mat4x2<f32> = tint_symbol_18(&(ub), 352u);
- var t : mat4x3<f32> = tint_symbol_19(&(ub), 384u);
- var u : mat4x4<f32> = tint_symbol_20(&(ub), 448u);
- var v : array<vec3<f32>, 2> = tint_symbol_21(&(ub), 512u);
+ var scalar_f32 : f32 = tint_symbol(&(ub), 0u);
+ var scalar_i32 : i32 = tint_symbol_1(&(ub), 4u);
+ var scalar_u32 : u32 = tint_symbol_2(&(ub), 8u);
+ var scalar_f16 : f16 = tint_symbol_3(&(ub), 12u);
+ var vec2_f32 : vec2<f32> = tint_symbol_4(&(ub), 16u);
+ var vec2_i32 : vec2<i32> = tint_symbol_5(&(ub), 24u);
+ var vec2_u32 : vec2<u32> = tint_symbol_6(&(ub), 32u);
+ var vec2_f16 : vec2<f16> = tint_symbol_7(&(ub), 40u);
+ var vec3_f32 : vec3<f32> = tint_symbol_8(&(ub), 48u);
+ var vec3_i32 : vec3<i32> = tint_symbol_9(&(ub), 64u);
+ var vec3_u32 : vec3<u32> = tint_symbol_10(&(ub), 80u);
+ var vec3_f16 : vec3<f16> = tint_symbol_11(&(ub), 96u);
+ var vec4_f32 : vec4<f32> = tint_symbol_12(&(ub), 112u);
+ var vec4_i32 : vec4<i32> = tint_symbol_13(&(ub), 128u);
+ var vec4_u32 : vec4<u32> = tint_symbol_14(&(ub), 144u);
+ var vec4_f16 : vec4<f16> = tint_symbol_15(&(ub), 160u);
+ var mat2x2_f32 : mat2x2<f32> = tint_symbol_16(&(ub), 168u);
+ var mat2x3_f32 : mat2x3<f32> = tint_symbol_17(&(ub), 192u);
+ var mat2x4_f32 : mat2x4<f32> = tint_symbol_18(&(ub), 224u);
+ var mat3x2_f32 : mat3x2<f32> = tint_symbol_19(&(ub), 256u);
+ var mat3x3_f32 : mat3x3<f32> = tint_symbol_20(&(ub), 288u);
+ var mat3x4_f32 : mat3x4<f32> = tint_symbol_21(&(ub), 336u);
+ var mat4x2_f32 : mat4x2<f32> = tint_symbol_22(&(ub), 384u);
+ var mat4x3_f32 : mat4x3<f32> = tint_symbol_23(&(ub), 416u);
+ var mat4x4_f32 : mat4x4<f32> = tint_symbol_24(&(ub), 480u);
+ var mat2x2_f16 : mat2x2<f16> = tint_symbol_25(&(ub), 544u);
+ var mat2x3_f16 : mat2x3<f16> = tint_symbol_26(&(ub), 552u);
+ var mat2x4_f16 : mat2x4<f16> = tint_symbol_27(&(ub), 568u);
+ var mat3x2_f16 : mat3x2<f16> = tint_symbol_28(&(ub), 584u);
+ var mat3x3_f16 : mat3x3<f16> = tint_symbol_29(&(ub), 600u);
+ var mat3x4_f16 : mat3x4<f16> = tint_symbol_30(&(ub), 624u);
+ var mat4x2_f16 : mat4x2<f16> = tint_symbol_31(&(ub), 648u);
+ var mat4x3_f16 : mat4x3<f16> = tint_symbol_32(&(ub), 664u);
+ var mat4x4_f16 : mat4x4<f16> = tint_symbol_33(&(ub), 696u);
+ var arr2_vec3_f32 : array<vec3<f32>, 2> = tint_symbol_34(&(ub), 736u);
+ var arr2_mat4x2_f16 : array<mat4x2<f16>, 2> = tint_symbol_35(&(ub), 768u);
}
@group(0) @binding(0) var<uniform> ub : UB;
struct UB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
)";
@@ -835,209 +1299,342 @@
TEST_F(DecomposeMemoryAccessTest, SB_BasicStore) {
auto* src = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
@group(0) @binding(0) var<storage, read_write> sb : SB;
@compute @workgroup_size(1)
fn main() {
- sb.a = i32();
- sb.b = u32();
- sb.c = f32();
- sb.d = vec2<i32>();
- sb.e = vec2<u32>();
- sb.f = vec2<f32>();
- sb.g = vec3<i32>();
- sb.h = vec3<u32>();
- sb.i = vec3<f32>();
- sb.j = vec4<i32>();
- sb.k = vec4<u32>();
- sb.l = vec4<f32>();
- sb.m = mat2x2<f32>();
- sb.n = mat2x3<f32>();
- sb.o = mat2x4<f32>();
- sb.p = mat3x2<f32>();
- sb.q = mat3x3<f32>();
- sb.r = mat3x4<f32>();
- sb.s = mat4x2<f32>();
- sb.t = mat4x3<f32>();
- sb.u = mat4x4<f32>();
- sb.v = array<vec3<f32>, 2>();
+ sb.scalar_f32 = f32();
+ sb.scalar_i32 = i32();
+ sb.scalar_u32 = u32();
+ sb.scalar_f16 = f16();
+ sb.vec2_f32 = vec2<f32>();
+ sb.vec2_i32 = vec2<i32>();
+ sb.vec2_u32 = vec2<u32>();
+ sb.vec2_f16 = vec2<f16>();
+ sb.vec3_f32 = vec3<f32>();
+ sb.vec3_i32 = vec3<i32>();
+ sb.vec3_u32 = vec3<u32>();
+ sb.vec3_f16 = vec3<f16>();
+ sb.vec4_f32 = vec4<f32>();
+ sb.vec4_i32 = vec4<i32>();
+ sb.vec4_u32 = vec4<u32>();
+ sb.vec4_f16 = vec4<f16>();
+ sb.mat2x2_f32 = mat2x2<f32>();
+ sb.mat2x3_f32 = mat2x3<f32>();
+ sb.mat2x4_f32 = mat2x4<f32>();
+ sb.mat3x2_f32 = mat3x2<f32>();
+ sb.mat3x3_f32 = mat3x3<f32>();
+ sb.mat3x4_f32 = mat3x4<f32>();
+ sb.mat4x2_f32 = mat4x2<f32>();
+ sb.mat4x3_f32 = mat4x3<f32>();
+ sb.mat4x4_f32 = mat4x4<f32>();
+ sb.mat2x2_f16 = mat2x2<f16>();
+ sb.mat2x3_f16 = mat2x3<f16>();
+ sb.mat2x4_f16 = mat2x4<f16>();
+ sb.mat3x2_f16 = mat3x2<f16>();
+ sb.mat3x3_f16 = mat3x3<f16>();
+ sb.mat3x4_f16 = mat3x4<f16>();
+ sb.mat4x2_f16 = mat4x2<f16>();
+ sb.mat4x3_f16 = mat4x3<f16>();
+ sb.mat4x4_f16 = mat4x4<f16>();
+ sb.arr2_vec3_f32 = array<vec3<f32>, 2>();
+ sb.arr2_mat4x2_f16 = array<mat4x2<f16>, 2>();
}
)";
auto* expect = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
+@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
+
@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
-@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
-
-@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
-
-@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+@internal(intrinsic_store_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f16)
@internal(intrinsic_store_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
-@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
+@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
-@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+
+@internal(intrinsic_store_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f16>)
@internal(intrinsic_store_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f32>)
-@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
-@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+
+@internal(intrinsic_store_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f16>)
@internal(intrinsic_store_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
- tint_symbol_5(buffer, (offset + 0u), value[0u]);
- tint_symbol_5(buffer, (offset + 8u), value[1u]);
+@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+
+@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+
+@internal(intrinsic_store_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f16>)
+
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
+ tint_symbol_4(buffer, (offset + 0u), value[0u]);
+ tint_symbol_4(buffer, (offset + 8u), value[1u]);
}
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
tint_symbol_8(buffer, (offset + 0u), value[0u]);
tint_symbol_8(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
- tint_symbol_11(buffer, (offset + 0u), value[0u]);
- tint_symbol_11(buffer, (offset + 16u), value[1u]);
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
- tint_symbol_5(buffer, (offset + 0u), value[0u]);
- tint_symbol_5(buffer, (offset + 8u), value[1u]);
- tint_symbol_5(buffer, (offset + 16u), value[2u]);
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
+ tint_symbol_4(buffer, (offset + 0u), value[0u]);
+ tint_symbol_4(buffer, (offset + 8u), value[1u]);
+ tint_symbol_4(buffer, (offset + 16u), value[2u]);
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
tint_symbol_8(buffer, (offset + 0u), value[0u]);
tint_symbol_8(buffer, (offset + 16u), value[1u]);
tint_symbol_8(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
- tint_symbol_11(buffer, (offset + 0u), value[0u]);
- tint_symbol_11(buffer, (offset + 16u), value[1u]);
- tint_symbol_11(buffer, (offset + 32u), value[2u]);
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 16u), value[1u]);
+ tint_symbol_12(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
- tint_symbol_5(buffer, (offset + 0u), value[0u]);
- tint_symbol_5(buffer, (offset + 8u), value[1u]);
- tint_symbol_5(buffer, (offset + 16u), value[2u]);
- tint_symbol_5(buffer, (offset + 24u), value[3u]);
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
+ tint_symbol_4(buffer, (offset + 0u), value[0u]);
+ tint_symbol_4(buffer, (offset + 8u), value[1u]);
+ tint_symbol_4(buffer, (offset + 16u), value[2u]);
+ tint_symbol_4(buffer, (offset + 24u), value[3u]);
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
tint_symbol_8(buffer, (offset + 0u), value[0u]);
tint_symbol_8(buffer, (offset + 16u), value[1u]);
tint_symbol_8(buffer, (offset + 32u), value[2u]);
tint_symbol_8(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
- tint_symbol_11(buffer, (offset + 0u), value[0u]);
- tint_symbol_11(buffer, (offset + 16u), value[1u]);
- tint_symbol_11(buffer, (offset + 32u), value[2u]);
- tint_symbol_11(buffer, (offset + 48u), value[3u]);
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 16u), value[1u]);
+ tint_symbol_12(buffer, (offset + 32u), value[2u]);
+ tint_symbol_12(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f16>) {
+ tint_symbol_7(buffer, (offset + 0u), value[0u]);
+ tint_symbol_7(buffer, (offset + 4u), value[1u]);
+}
+
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f16>) {
+ tint_symbol_11(buffer, (offset + 0u), value[0u]);
+ tint_symbol_11(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f16>) {
+ tint_symbol_15(buffer, (offset + 0u), value[0u]);
+ tint_symbol_15(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f16>) {
+ tint_symbol_7(buffer, (offset + 0u), value[0u]);
+ tint_symbol_7(buffer, (offset + 4u), value[1u]);
+ tint_symbol_7(buffer, (offset + 8u), value[2u]);
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f16>) {
+ tint_symbol_11(buffer, (offset + 0u), value[0u]);
+ tint_symbol_11(buffer, (offset + 8u), value[1u]);
+ tint_symbol_11(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f16>) {
+ tint_symbol_15(buffer, (offset + 0u), value[0u]);
+ tint_symbol_15(buffer, (offset + 8u), value[1u]);
+ tint_symbol_15(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f16>) {
+ tint_symbol_7(buffer, (offset + 0u), value[0u]);
+ tint_symbol_7(buffer, (offset + 4u), value[1u]);
+ tint_symbol_7(buffer, (offset + 8u), value[2u]);
+ tint_symbol_7(buffer, (offset + 12u), value[3u]);
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f16>) {
+ tint_symbol_11(buffer, (offset + 0u), value[0u]);
+ tint_symbol_11(buffer, (offset + 8u), value[1u]);
+ tint_symbol_11(buffer, (offset + 16u), value[2u]);
+ tint_symbol_11(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f16>) {
+ tint_symbol_15(buffer, (offset + 0u), value[0u]);
+ tint_symbol_15(buffer, (offset + 8u), value[1u]);
+ tint_symbol_15(buffer, (offset + 16u), value[2u]);
+ tint_symbol_15(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
var array = value;
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ tint_symbol_8(buffer, (offset + (i * 16u)), array[i]);
+ }
+}
+
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<mat4x2<f16>, 2u>) {
+ var array_1 = value;
for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- tint_symbol_8(buffer, (offset + (i_1 * 16u)), array[i_1]);
+ tint_symbol_31(buffer, (offset + (i_1 * 16u)), array_1[i_1]);
}
}
@compute @workgroup_size(1)
fn main() {
- tint_symbol(&(sb), 0u, i32());
- tint_symbol_1(&(sb), 4u, u32());
- tint_symbol_2(&(sb), 8u, f32());
- tint_symbol_3(&(sb), 16u, vec2<i32>());
- tint_symbol_4(&(sb), 24u, vec2<u32>());
- tint_symbol_5(&(sb), 32u, vec2<f32>());
- tint_symbol_6(&(sb), 48u, vec3<i32>());
- tint_symbol_7(&(sb), 64u, vec3<u32>());
- tint_symbol_8(&(sb), 80u, vec3<f32>());
- tint_symbol_9(&(sb), 96u, vec4<i32>());
- tint_symbol_10(&(sb), 112u, vec4<u32>());
- tint_symbol_11(&(sb), 128u, vec4<f32>());
- tint_symbol_12(&(sb), 144u, mat2x2<f32>());
- tint_symbol_13(&(sb), 160u, mat2x3<f32>());
- tint_symbol_14(&(sb), 192u, mat2x4<f32>());
- tint_symbol_15(&(sb), 224u, mat3x2<f32>());
- tint_symbol_16(&(sb), 256u, mat3x3<f32>());
- tint_symbol_17(&(sb), 304u, mat3x4<f32>());
- tint_symbol_18(&(sb), 352u, mat4x2<f32>());
- tint_symbol_19(&(sb), 384u, mat4x3<f32>());
- tint_symbol_20(&(sb), 448u, mat4x4<f32>());
- tint_symbol_21(&(sb), 512u, array<vec3<f32>, 2>());
+ tint_symbol(&(sb), 0u, f32());
+ tint_symbol_1(&(sb), 4u, i32());
+ tint_symbol_2(&(sb), 8u, u32());
+ tint_symbol_3(&(sb), 12u, f16());
+ tint_symbol_4(&(sb), 16u, vec2<f32>());
+ tint_symbol_5(&(sb), 24u, vec2<i32>());
+ tint_symbol_6(&(sb), 32u, vec2<u32>());
+ tint_symbol_7(&(sb), 40u, vec2<f16>());
+ tint_symbol_8(&(sb), 48u, vec3<f32>());
+ tint_symbol_9(&(sb), 64u, vec3<i32>());
+ tint_symbol_10(&(sb), 80u, vec3<u32>());
+ tint_symbol_11(&(sb), 96u, vec3<f16>());
+ tint_symbol_12(&(sb), 112u, vec4<f32>());
+ tint_symbol_13(&(sb), 128u, vec4<i32>());
+ tint_symbol_14(&(sb), 144u, vec4<u32>());
+ tint_symbol_15(&(sb), 160u, vec4<f16>());
+ tint_symbol_16(&(sb), 168u, mat2x2<f32>());
+ tint_symbol_17(&(sb), 192u, mat2x3<f32>());
+ tint_symbol_18(&(sb), 224u, mat2x4<f32>());
+ tint_symbol_19(&(sb), 256u, mat3x2<f32>());
+ tint_symbol_20(&(sb), 288u, mat3x3<f32>());
+ tint_symbol_21(&(sb), 336u, mat3x4<f32>());
+ tint_symbol_22(&(sb), 384u, mat4x2<f32>());
+ tint_symbol_23(&(sb), 416u, mat4x3<f32>());
+ tint_symbol_24(&(sb), 480u, mat4x4<f32>());
+ tint_symbol_25(&(sb), 544u, mat2x2<f16>());
+ tint_symbol_26(&(sb), 552u, mat2x3<f16>());
+ tint_symbol_27(&(sb), 568u, mat2x4<f16>());
+ tint_symbol_28(&(sb), 584u, mat3x2<f16>());
+ tint_symbol_29(&(sb), 600u, mat3x3<f16>());
+ tint_symbol_30(&(sb), 624u, mat3x4<f16>());
+ tint_symbol_31(&(sb), 648u, mat4x2<f16>());
+ tint_symbol_32(&(sb), 664u, mat4x3<f16>());
+ tint_symbol_33(&(sb), 696u, mat4x4<f16>());
+ tint_symbol_34(&(sb), 736u, array<vec3<f32>, 2>());
+ tint_symbol_35(&(sb), 768u, array<mat4x2<f16>, 2>());
}
)";
@@ -1048,209 +1645,342 @@
TEST_F(DecomposeMemoryAccessTest, SB_BasicStore_OutOfOrder) {
auto* src = R"(
+enable f16;
+
@compute @workgroup_size(1)
fn main() {
- sb.a = i32();
- sb.b = u32();
- sb.c = f32();
- sb.d = vec2<i32>();
- sb.e = vec2<u32>();
- sb.f = vec2<f32>();
- sb.g = vec3<i32>();
- sb.h = vec3<u32>();
- sb.i = vec3<f32>();
- sb.j = vec4<i32>();
- sb.k = vec4<u32>();
- sb.l = vec4<f32>();
- sb.m = mat2x2<f32>();
- sb.n = mat2x3<f32>();
- sb.o = mat2x4<f32>();
- sb.p = mat3x2<f32>();
- sb.q = mat3x3<f32>();
- sb.r = mat3x4<f32>();
- sb.s = mat4x2<f32>();
- sb.t = mat4x3<f32>();
- sb.u = mat4x4<f32>();
- sb.v = array<vec3<f32>, 2>();
+ sb.scalar_f32 = f32();
+ sb.scalar_i32 = i32();
+ sb.scalar_u32 = u32();
+ sb.scalar_f16 = f16();
+ sb.vec2_f32 = vec2<f32>();
+ sb.vec2_i32 = vec2<i32>();
+ sb.vec2_u32 = vec2<u32>();
+ sb.vec2_f16 = vec2<f16>();
+ sb.vec3_f32 = vec3<f32>();
+ sb.vec3_i32 = vec3<i32>();
+ sb.vec3_u32 = vec3<u32>();
+ sb.vec3_f16 = vec3<f16>();
+ sb.vec4_f32 = vec4<f32>();
+ sb.vec4_i32 = vec4<i32>();
+ sb.vec4_u32 = vec4<u32>();
+ sb.vec4_f16 = vec4<f16>();
+ sb.mat2x2_f32 = mat2x2<f32>();
+ sb.mat2x3_f32 = mat2x3<f32>();
+ sb.mat2x4_f32 = mat2x4<f32>();
+ sb.mat3x2_f32 = mat3x2<f32>();
+ sb.mat3x3_f32 = mat3x3<f32>();
+ sb.mat3x4_f32 = mat3x4<f32>();
+ sb.mat4x2_f32 = mat4x2<f32>();
+ sb.mat4x3_f32 = mat4x3<f32>();
+ sb.mat4x4_f32 = mat4x4<f32>();
+ sb.mat2x2_f16 = mat2x2<f16>();
+ sb.mat2x3_f16 = mat2x3<f16>();
+ sb.mat2x4_f16 = mat2x4<f16>();
+ sb.mat3x2_f16 = mat3x2<f16>();
+ sb.mat3x3_f16 = mat3x3<f16>();
+ sb.mat3x4_f16 = mat3x4<f16>();
+ sb.mat4x2_f16 = mat4x2<f16>();
+ sb.mat4x3_f16 = mat4x3<f16>();
+ sb.mat4x4_f16 = mat4x4<f16>();
+ sb.arr2_vec3_f32 = array<vec3<f32>, 2>();
+ sb.arr2_mat4x2_f16 = array<mat4x2<f16>, 2>();
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
)";
auto* expect = R"(
-@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
-
-@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
+enable f16;
@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
+fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
-@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
+@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
-@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
+
+@internal(intrinsic_store_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f16)
@internal(intrinsic_store_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
-@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
+@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
-@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+
+@internal(intrinsic_store_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f16>)
@internal(intrinsic_store_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f32>)
-@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
-@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+
+@internal(intrinsic_store_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f16>)
@internal(intrinsic_store_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
- tint_symbol_5(buffer, (offset + 0u), value[0u]);
- tint_symbol_5(buffer, (offset + 8u), value[1u]);
+@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+
+@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+
+@internal(intrinsic_store_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f16>)
+
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
+ tint_symbol_4(buffer, (offset + 0u), value[0u]);
+ tint_symbol_4(buffer, (offset + 8u), value[1u]);
}
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
tint_symbol_8(buffer, (offset + 0u), value[0u]);
tint_symbol_8(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
- tint_symbol_11(buffer, (offset + 0u), value[0u]);
- tint_symbol_11(buffer, (offset + 16u), value[1u]);
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
- tint_symbol_5(buffer, (offset + 0u), value[0u]);
- tint_symbol_5(buffer, (offset + 8u), value[1u]);
- tint_symbol_5(buffer, (offset + 16u), value[2u]);
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
+ tint_symbol_4(buffer, (offset + 0u), value[0u]);
+ tint_symbol_4(buffer, (offset + 8u), value[1u]);
+ tint_symbol_4(buffer, (offset + 16u), value[2u]);
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
tint_symbol_8(buffer, (offset + 0u), value[0u]);
tint_symbol_8(buffer, (offset + 16u), value[1u]);
tint_symbol_8(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
- tint_symbol_11(buffer, (offset + 0u), value[0u]);
- tint_symbol_11(buffer, (offset + 16u), value[1u]);
- tint_symbol_11(buffer, (offset + 32u), value[2u]);
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 16u), value[1u]);
+ tint_symbol_12(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
- tint_symbol_5(buffer, (offset + 0u), value[0u]);
- tint_symbol_5(buffer, (offset + 8u), value[1u]);
- tint_symbol_5(buffer, (offset + 16u), value[2u]);
- tint_symbol_5(buffer, (offset + 24u), value[3u]);
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
+ tint_symbol_4(buffer, (offset + 0u), value[0u]);
+ tint_symbol_4(buffer, (offset + 8u), value[1u]);
+ tint_symbol_4(buffer, (offset + 16u), value[2u]);
+ tint_symbol_4(buffer, (offset + 24u), value[3u]);
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
tint_symbol_8(buffer, (offset + 0u), value[0u]);
tint_symbol_8(buffer, (offset + 16u), value[1u]);
tint_symbol_8(buffer, (offset + 32u), value[2u]);
tint_symbol_8(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
- tint_symbol_11(buffer, (offset + 0u), value[0u]);
- tint_symbol_11(buffer, (offset + 16u), value[1u]);
- tint_symbol_11(buffer, (offset + 32u), value[2u]);
- tint_symbol_11(buffer, (offset + 48u), value[3u]);
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 16u), value[1u]);
+ tint_symbol_12(buffer, (offset + 32u), value[2u]);
+ tint_symbol_12(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f16>) {
+ tint_symbol_7(buffer, (offset + 0u), value[0u]);
+ tint_symbol_7(buffer, (offset + 4u), value[1u]);
+}
+
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f16>) {
+ tint_symbol_11(buffer, (offset + 0u), value[0u]);
+ tint_symbol_11(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f16>) {
+ tint_symbol_15(buffer, (offset + 0u), value[0u]);
+ tint_symbol_15(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f16>) {
+ tint_symbol_7(buffer, (offset + 0u), value[0u]);
+ tint_symbol_7(buffer, (offset + 4u), value[1u]);
+ tint_symbol_7(buffer, (offset + 8u), value[2u]);
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f16>) {
+ tint_symbol_11(buffer, (offset + 0u), value[0u]);
+ tint_symbol_11(buffer, (offset + 8u), value[1u]);
+ tint_symbol_11(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f16>) {
+ tint_symbol_15(buffer, (offset + 0u), value[0u]);
+ tint_symbol_15(buffer, (offset + 8u), value[1u]);
+ tint_symbol_15(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f16>) {
+ tint_symbol_7(buffer, (offset + 0u), value[0u]);
+ tint_symbol_7(buffer, (offset + 4u), value[1u]);
+ tint_symbol_7(buffer, (offset + 8u), value[2u]);
+ tint_symbol_7(buffer, (offset + 12u), value[3u]);
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f16>) {
+ tint_symbol_11(buffer, (offset + 0u), value[0u]);
+ tint_symbol_11(buffer, (offset + 8u), value[1u]);
+ tint_symbol_11(buffer, (offset + 16u), value[2u]);
+ tint_symbol_11(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f16>) {
+ tint_symbol_15(buffer, (offset + 0u), value[0u]);
+ tint_symbol_15(buffer, (offset + 8u), value[1u]);
+ tint_symbol_15(buffer, (offset + 16u), value[2u]);
+ tint_symbol_15(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
var array = value;
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ tint_symbol_8(buffer, (offset + (i * 16u)), array[i]);
+ }
+}
+
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<mat4x2<f16>, 2u>) {
+ var array_1 = value;
for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- tint_symbol_8(buffer, (offset + (i_1 * 16u)), array[i_1]);
+ tint_symbol_31(buffer, (offset + (i_1 * 16u)), array_1[i_1]);
}
}
@compute @workgroup_size(1)
fn main() {
- tint_symbol(&(sb), 0u, i32());
- tint_symbol_1(&(sb), 4u, u32());
- tint_symbol_2(&(sb), 8u, f32());
- tint_symbol_3(&(sb), 16u, vec2<i32>());
- tint_symbol_4(&(sb), 24u, vec2<u32>());
- tint_symbol_5(&(sb), 32u, vec2<f32>());
- tint_symbol_6(&(sb), 48u, vec3<i32>());
- tint_symbol_7(&(sb), 64u, vec3<u32>());
- tint_symbol_8(&(sb), 80u, vec3<f32>());
- tint_symbol_9(&(sb), 96u, vec4<i32>());
- tint_symbol_10(&(sb), 112u, vec4<u32>());
- tint_symbol_11(&(sb), 128u, vec4<f32>());
- tint_symbol_12(&(sb), 144u, mat2x2<f32>());
- tint_symbol_13(&(sb), 160u, mat2x3<f32>());
- tint_symbol_14(&(sb), 192u, mat2x4<f32>());
- tint_symbol_15(&(sb), 224u, mat3x2<f32>());
- tint_symbol_16(&(sb), 256u, mat3x3<f32>());
- tint_symbol_17(&(sb), 304u, mat3x4<f32>());
- tint_symbol_18(&(sb), 352u, mat4x2<f32>());
- tint_symbol_19(&(sb), 384u, mat4x3<f32>());
- tint_symbol_20(&(sb), 448u, mat4x4<f32>());
- tint_symbol_21(&(sb), 512u, array<vec3<f32>, 2>());
+ tint_symbol(&(sb), 0u, f32());
+ tint_symbol_1(&(sb), 4u, i32());
+ tint_symbol_2(&(sb), 8u, u32());
+ tint_symbol_3(&(sb), 12u, f16());
+ tint_symbol_4(&(sb), 16u, vec2<f32>());
+ tint_symbol_5(&(sb), 24u, vec2<i32>());
+ tint_symbol_6(&(sb), 32u, vec2<u32>());
+ tint_symbol_7(&(sb), 40u, vec2<f16>());
+ tint_symbol_8(&(sb), 48u, vec3<f32>());
+ tint_symbol_9(&(sb), 64u, vec3<i32>());
+ tint_symbol_10(&(sb), 80u, vec3<u32>());
+ tint_symbol_11(&(sb), 96u, vec3<f16>());
+ tint_symbol_12(&(sb), 112u, vec4<f32>());
+ tint_symbol_13(&(sb), 128u, vec4<i32>());
+ tint_symbol_14(&(sb), 144u, vec4<u32>());
+ tint_symbol_15(&(sb), 160u, vec4<f16>());
+ tint_symbol_16(&(sb), 168u, mat2x2<f32>());
+ tint_symbol_17(&(sb), 192u, mat2x3<f32>());
+ tint_symbol_18(&(sb), 224u, mat2x4<f32>());
+ tint_symbol_19(&(sb), 256u, mat3x2<f32>());
+ tint_symbol_20(&(sb), 288u, mat3x3<f32>());
+ tint_symbol_21(&(sb), 336u, mat3x4<f32>());
+ tint_symbol_22(&(sb), 384u, mat4x2<f32>());
+ tint_symbol_23(&(sb), 416u, mat4x3<f32>());
+ tint_symbol_24(&(sb), 480u, mat4x4<f32>());
+ tint_symbol_25(&(sb), 544u, mat2x2<f16>());
+ tint_symbol_26(&(sb), 552u, mat2x3<f16>());
+ tint_symbol_27(&(sb), 568u, mat2x4<f16>());
+ tint_symbol_28(&(sb), 584u, mat3x2<f16>());
+ tint_symbol_29(&(sb), 600u, mat3x3<f16>());
+ tint_symbol_30(&(sb), 624u, mat3x4<f16>());
+ tint_symbol_31(&(sb), 648u, mat4x2<f16>());
+ tint_symbol_32(&(sb), 664u, mat4x3<f16>());
+ tint_symbol_33(&(sb), 696u, mat4x4<f16>());
+ tint_symbol_34(&(sb), 736u, array<vec3<f32>, 2>());
+ tint_symbol_35(&(sb), 768u, array<mat4x2<f16>, 2>());
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
)";
@@ -1261,29 +1991,45 @@
TEST_F(DecomposeMemoryAccessTest, LoadStructure) {
auto* src = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
@group(0) @binding(0) var<storage, read_write> sb : SB;
@@ -1295,115 +2041,187 @@
)";
auto* expect = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
+@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
+
@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
-@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
-
-@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
-
-@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f16
@internal(intrinsic_load_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
-@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
-@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+
+@internal(intrinsic_load_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f16>
@internal(intrinsic_load_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f32>
-@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
-@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+
+@internal(intrinsic_load_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f16>
@internal(intrinsic_load_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
- return mat2x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)));
+@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+
+@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+
+@internal(intrinsic_load_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f16>
+
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
+ return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
return mat2x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)));
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
- return mat2x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)));
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
+ return mat2x4<f32>(tint_symbol_13(buffer, (offset + 0u)), tint_symbol_13(buffer, (offset + 16u)));
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
- return mat3x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)), tint_symbol_6(buffer, (offset + 16u)));
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
+ return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
return mat3x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)), tint_symbol_9(buffer, (offset + 32u)));
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
- return mat3x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)));
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
+ return mat3x4<f32>(tint_symbol_13(buffer, (offset + 0u)), tint_symbol_13(buffer, (offset + 16u)), tint_symbol_13(buffer, (offset + 32u)));
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
- return mat4x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)), tint_symbol_6(buffer, (offset + 16u)), tint_symbol_6(buffer, (offset + 24u)));
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
+ return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
return mat4x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)), tint_symbol_9(buffer, (offset + 32u)), tint_symbol_9(buffer, (offset + 48u)));
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
- return mat4x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)), tint_symbol_12(buffer, (offset + 48u)));
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
+ return mat4x4<f32>(tint_symbol_13(buffer, (offset + 0u)), tint_symbol_13(buffer, (offset + 16u)), tint_symbol_13(buffer, (offset + 32u)), tint_symbol_13(buffer, (offset + 48u)));
}
-fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f16> {
+ return mat2x2<f16>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 4u)));
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f16> {
+ return mat2x3<f16>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f16> {
+ return mat2x4<f16>(tint_symbol_16(buffer, (offset + 0u)), tint_symbol_16(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f16> {
+ return mat3x2<f16>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 4u)), tint_symbol_8(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f16> {
+ return mat3x3<f16>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 8u)), tint_symbol_12(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f16> {
+ return mat3x4<f16>(tint_symbol_16(buffer, (offset + 0u)), tint_symbol_16(buffer, (offset + 8u)), tint_symbol_16(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f16> {
+ return mat4x2<f16>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 4u)), tint_symbol_8(buffer, (offset + 8u)), tint_symbol_8(buffer, (offset + 12u)));
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f16> {
+ return mat4x3<f16>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 8u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f16> {
+ return mat4x4<f16>(tint_symbol_16(buffer, (offset + 0u)), tint_symbol_16(buffer, (offset + 8u)), tint_symbol_16(buffer, (offset + 16u)), tint_symbol_16(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
var arr : array<vec3<f32>, 2u>;
- for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- arr[i_1] = tint_symbol_9(buffer, (offset + (i_1 * 16u)));
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ arr[i] = tint_symbol_9(buffer, (offset + (i * 16u)));
}
return arr;
}
+fn tint_symbol_36(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<mat4x2<f16>, 2u> {
+ var arr_1 : array<mat4x2<f16>, 2u>;
+ for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
+ arr_1[i_1] = tint_symbol_32(buffer, (offset + (i_1 * 16u)));
+ }
+ return arr_1;
+}
+
fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> SB {
- return SB(tint_symbol_1(buffer, (offset + 0u)), tint_symbol_2(buffer, (offset + 4u)), tint_symbol_3(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)), tint_symbol_6(buffer, (offset + 32u)), tint_symbol_7(buffer, (offset + 48u)), tint_symbol_8(buffer, (offset + 64u)), tint_symbol_9(buffer, (offset + 80u)), tint_symbol_10(buffer, (offset + 96u)), tint_symbol_11(buffer, (offset + 112u)), tint_symbol_12(buffer, (offset + 128u)), tint_symbol_13(buffer, (offset + 144u)), tint_symbol_14(buffer, (offset + 160u)), tint_symbol_15(buffer, (offset + 192u)), tint_symbol_16(buffer, (offset + 224u)), tint_symbol_17(buffer, (offset + 256u)), tint_symbol_18(buffer, (offset + 304u)), tint_symbol_19(buffer, (offset + 352u)), tint_symbol_20(buffer, (offset + 384u)), tint_symbol_21(buffer, (offset + 448u)), tint_symbol_22(buffer, (offset + 512u)));
+ return SB(tint_symbol_1(buffer, (offset + 0u)), tint_symbol_2(buffer, (offset + 4u)), tint_symbol_3(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 12u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_6(buffer, (offset + 24u)), tint_symbol_7(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 40u)), tint_symbol_9(buffer, (offset + 48u)), tint_symbol_10(buffer, (offset + 64u)), tint_symbol_11(buffer, (offset + 80u)), tint_symbol_12(buffer, (offset + 96u)), tint_symbol_13(buffer, (offset + 112u)), tint_symbol_14(buffer, (offset + 128u)), tint_symbol_15(buffer, (offset + 144u)), tint_symbol_16(buffer, (offset + 160u)), tint_symbol_17(buffer, (offset + 168u)), tint_symbol_18(buffer, (offset + 192u)), tint_symbol_19(buffer, (offset + 224u)), tint_symbol_20(buffer, (offset + 256u)), tint_symbol_21(buffer, (offset + 288u)), tint_symbol_22(buffer, (offset + 336u)), tint_symbol_23(buffer, (offset + 384u)), tint_symbol_24(buffer, (offset + 416u)), tint_symbol_25(buffer, (offset + 480u)), tint_symbol_26(buffer, (offset + 544u)), tint_symbol_27(buffer, (offset + 552u)), tint_symbol_28(buffer, (offset + 568u)), tint_symbol_29(buffer, (offset + 584u)), tint_symbol_30(buffer, (offset + 600u)), tint_symbol_31(buffer, (offset + 624u)), tint_symbol_32(buffer, (offset + 648u)), tint_symbol_33(buffer, (offset + 664u)), tint_symbol_34(buffer, (offset + 696u)), tint_symbol_35(buffer, (offset + 736u)), tint_symbol_36(buffer, (offset + 768u)));
}
@compute @workgroup_size(1)
@@ -1419,6 +2237,8 @@
TEST_F(DecomposeMemoryAccessTest, LoadStructure_OutOfOrder) {
auto* src = R"(
+enable f16;
+
@compute @workgroup_size(1)
fn main() {
var x : SB = sb;
@@ -1427,114 +2247,186 @@
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
)";
auto* expect = R"(
-@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
-
-@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
+enable f16;
@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f32
-@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
+@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> i32
-@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> u32
+
+@internal(intrinsic_load_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> f16
@internal(intrinsic_load_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f32>
-@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<i32>
-@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<u32>
+
+@internal(intrinsic_load_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec2<f16>
@internal(intrinsic_load_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f32>
-@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<i32>
-@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<u32>
+
+@internal(intrinsic_load_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec3<f16>
@internal(intrinsic_load_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f32>
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
- return mat2x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)));
+@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<i32>
+
+@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<u32>
+
+@internal(intrinsic_load_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> vec4<f16>
+
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f32> {
+ return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f32> {
return mat2x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)));
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
- return mat2x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)));
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f32> {
+ return mat2x4<f32>(tint_symbol_13(buffer, (offset + 0u)), tint_symbol_13(buffer, (offset + 16u)));
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
- return mat3x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)), tint_symbol_6(buffer, (offset + 16u)));
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f32> {
+ return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f32> {
return mat3x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)), tint_symbol_9(buffer, (offset + 32u)));
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
- return mat3x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)));
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f32> {
+ return mat3x4<f32>(tint_symbol_13(buffer, (offset + 0u)), tint_symbol_13(buffer, (offset + 16u)), tint_symbol_13(buffer, (offset + 32u)));
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
- return mat4x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)), tint_symbol_6(buffer, (offset + 16u)), tint_symbol_6(buffer, (offset + 24u)));
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f32> {
+ return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f32> {
return mat4x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)), tint_symbol_9(buffer, (offset + 32u)), tint_symbol_9(buffer, (offset + 48u)));
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
- return mat4x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)), tint_symbol_12(buffer, (offset + 48u)));
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f32> {
+ return mat4x4<f32>(tint_symbol_13(buffer, (offset + 0u)), tint_symbol_13(buffer, (offset + 16u)), tint_symbol_13(buffer, (offset + 32u)), tint_symbol_13(buffer, (offset + 48u)));
}
-fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x2<f16> {
+ return mat2x2<f16>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 4u)));
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x3<f16> {
+ return mat2x3<f16>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat2x4<f16> {
+ return mat2x4<f16>(tint_symbol_16(buffer, (offset + 0u)), tint_symbol_16(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x2<f16> {
+ return mat3x2<f16>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 4u)), tint_symbol_8(buffer, (offset + 8u)));
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x3<f16> {
+ return mat3x3<f16>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 8u)), tint_symbol_12(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat3x4<f16> {
+ return mat3x4<f16>(tint_symbol_16(buffer, (offset + 0u)), tint_symbol_16(buffer, (offset + 8u)), tint_symbol_16(buffer, (offset + 16u)));
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x2<f16> {
+ return mat4x2<f16>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 4u)), tint_symbol_8(buffer, (offset + 8u)), tint_symbol_8(buffer, (offset + 12u)));
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x3<f16> {
+ return mat4x3<f16>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 8u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> mat4x4<f16> {
+ return mat4x4<f16>(tint_symbol_16(buffer, (offset + 0u)), tint_symbol_16(buffer, (offset + 8u)), tint_symbol_16(buffer, (offset + 16u)), tint_symbol_16(buffer, (offset + 24u)));
+}
+
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<vec3<f32>, 2u> {
var arr : array<vec3<f32>, 2u>;
- for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- arr[i_1] = tint_symbol_9(buffer, (offset + (i_1 * 16u)));
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ arr[i] = tint_symbol_9(buffer, (offset + (i * 16u)));
}
return arr;
}
+fn tint_symbol_36(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> array<mat4x2<f16>, 2u> {
+ var arr_1 : array<mat4x2<f16>, 2u>;
+ for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
+ arr_1[i_1] = tint_symbol_32(buffer, (offset + (i_1 * 16u)));
+ }
+ return arr_1;
+}
+
fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32) -> SB {
- return SB(tint_symbol_1(buffer, (offset + 0u)), tint_symbol_2(buffer, (offset + 4u)), tint_symbol_3(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)), tint_symbol_6(buffer, (offset + 32u)), tint_symbol_7(buffer, (offset + 48u)), tint_symbol_8(buffer, (offset + 64u)), tint_symbol_9(buffer, (offset + 80u)), tint_symbol_10(buffer, (offset + 96u)), tint_symbol_11(buffer, (offset + 112u)), tint_symbol_12(buffer, (offset + 128u)), tint_symbol_13(buffer, (offset + 144u)), tint_symbol_14(buffer, (offset + 160u)), tint_symbol_15(buffer, (offset + 192u)), tint_symbol_16(buffer, (offset + 224u)), tint_symbol_17(buffer, (offset + 256u)), tint_symbol_18(buffer, (offset + 304u)), tint_symbol_19(buffer, (offset + 352u)), tint_symbol_20(buffer, (offset + 384u)), tint_symbol_21(buffer, (offset + 448u)), tint_symbol_22(buffer, (offset + 512u)));
+ return SB(tint_symbol_1(buffer, (offset + 0u)), tint_symbol_2(buffer, (offset + 4u)), tint_symbol_3(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 12u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_6(buffer, (offset + 24u)), tint_symbol_7(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 40u)), tint_symbol_9(buffer, (offset + 48u)), tint_symbol_10(buffer, (offset + 64u)), tint_symbol_11(buffer, (offset + 80u)), tint_symbol_12(buffer, (offset + 96u)), tint_symbol_13(buffer, (offset + 112u)), tint_symbol_14(buffer, (offset + 128u)), tint_symbol_15(buffer, (offset + 144u)), tint_symbol_16(buffer, (offset + 160u)), tint_symbol_17(buffer, (offset + 168u)), tint_symbol_18(buffer, (offset + 192u)), tint_symbol_19(buffer, (offset + 224u)), tint_symbol_20(buffer, (offset + 256u)), tint_symbol_21(buffer, (offset + 288u)), tint_symbol_22(buffer, (offset + 336u)), tint_symbol_23(buffer, (offset + 384u)), tint_symbol_24(buffer, (offset + 416u)), tint_symbol_25(buffer, (offset + 480u)), tint_symbol_26(buffer, (offset + 544u)), tint_symbol_27(buffer, (offset + 552u)), tint_symbol_28(buffer, (offset + 568u)), tint_symbol_29(buffer, (offset + 584u)), tint_symbol_30(buffer, (offset + 600u)), tint_symbol_31(buffer, (offset + 624u)), tint_symbol_32(buffer, (offset + 648u)), tint_symbol_33(buffer, (offset + 664u)), tint_symbol_34(buffer, (offset + 696u)), tint_symbol_35(buffer, (offset + 736u)), tint_symbol_36(buffer, (offset + 768u)));
}
@compute @workgroup_size(1)
@@ -1545,28 +2437,42 @@
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
)";
@@ -1577,29 +2483,45 @@
TEST_F(DecomposeMemoryAccessTest, StoreStructure) {
auto* src = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
@group(0) @binding(0) var<storage, read_write> sb : SB;
@@ -1611,153 +2533,256 @@
)";
auto* expect = R"(
+enable f16;
+
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
@group(0) @binding(0) var<storage, read_write> sb : SB;
+@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
+
@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
-@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
-
-@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
-
-@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+@internal(intrinsic_store_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f16)
@internal(intrinsic_store_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
-@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
+@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
-@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+
+@internal(intrinsic_store_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f16>)
@internal(intrinsic_store_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f32>)
-@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
-@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+
+@internal(intrinsic_store_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f16>)
@internal(intrinsic_store_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
- tint_symbol_6(buffer, (offset + 0u), value[0u]);
- tint_symbol_6(buffer, (offset + 8u), value[1u]);
+@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+
+@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+
+@internal(intrinsic_store_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f16>)
+
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
+ tint_symbol_5(buffer, (offset + 0u), value[0u]);
+ tint_symbol_5(buffer, (offset + 8u), value[1u]);
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
tint_symbol_9(buffer, (offset + 0u), value[0u]);
tint_symbol_9(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
- tint_symbol_12(buffer, (offset + 0u), value[0u]);
- tint_symbol_12(buffer, (offset + 16u), value[1u]);
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
+ tint_symbol_13(buffer, (offset + 0u), value[0u]);
+ tint_symbol_13(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
- tint_symbol_6(buffer, (offset + 0u), value[0u]);
- tint_symbol_6(buffer, (offset + 8u), value[1u]);
- tint_symbol_6(buffer, (offset + 16u), value[2u]);
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
+ tint_symbol_5(buffer, (offset + 0u), value[0u]);
+ tint_symbol_5(buffer, (offset + 8u), value[1u]);
+ tint_symbol_5(buffer, (offset + 16u), value[2u]);
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
tint_symbol_9(buffer, (offset + 0u), value[0u]);
tint_symbol_9(buffer, (offset + 16u), value[1u]);
tint_symbol_9(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
- tint_symbol_12(buffer, (offset + 0u), value[0u]);
- tint_symbol_12(buffer, (offset + 16u), value[1u]);
- tint_symbol_12(buffer, (offset + 32u), value[2u]);
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
+ tint_symbol_13(buffer, (offset + 0u), value[0u]);
+ tint_symbol_13(buffer, (offset + 16u), value[1u]);
+ tint_symbol_13(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
- tint_symbol_6(buffer, (offset + 0u), value[0u]);
- tint_symbol_6(buffer, (offset + 8u), value[1u]);
- tint_symbol_6(buffer, (offset + 16u), value[2u]);
- tint_symbol_6(buffer, (offset + 24u), value[3u]);
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
+ tint_symbol_5(buffer, (offset + 0u), value[0u]);
+ tint_symbol_5(buffer, (offset + 8u), value[1u]);
+ tint_symbol_5(buffer, (offset + 16u), value[2u]);
+ tint_symbol_5(buffer, (offset + 24u), value[3u]);
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
tint_symbol_9(buffer, (offset + 0u), value[0u]);
tint_symbol_9(buffer, (offset + 16u), value[1u]);
tint_symbol_9(buffer, (offset + 32u), value[2u]);
tint_symbol_9(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
- tint_symbol_12(buffer, (offset + 0u), value[0u]);
- tint_symbol_12(buffer, (offset + 16u), value[1u]);
- tint_symbol_12(buffer, (offset + 32u), value[2u]);
- tint_symbol_12(buffer, (offset + 48u), value[3u]);
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
+ tint_symbol_13(buffer, (offset + 0u), value[0u]);
+ tint_symbol_13(buffer, (offset + 16u), value[1u]);
+ tint_symbol_13(buffer, (offset + 32u), value[2u]);
+ tint_symbol_13(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f16>) {
+ tint_symbol_8(buffer, (offset + 0u), value[0u]);
+ tint_symbol_8(buffer, (offset + 4u), value[1u]);
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f16>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f16>) {
+ tint_symbol_16(buffer, (offset + 0u), value[0u]);
+ tint_symbol_16(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f16>) {
+ tint_symbol_8(buffer, (offset + 0u), value[0u]);
+ tint_symbol_8(buffer, (offset + 4u), value[1u]);
+ tint_symbol_8(buffer, (offset + 8u), value[2u]);
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f16>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 8u), value[1u]);
+ tint_symbol_12(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f16>) {
+ tint_symbol_16(buffer, (offset + 0u), value[0u]);
+ tint_symbol_16(buffer, (offset + 8u), value[1u]);
+ tint_symbol_16(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f16>) {
+ tint_symbol_8(buffer, (offset + 0u), value[0u]);
+ tint_symbol_8(buffer, (offset + 4u), value[1u]);
+ tint_symbol_8(buffer, (offset + 8u), value[2u]);
+ tint_symbol_8(buffer, (offset + 12u), value[3u]);
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f16>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 8u), value[1u]);
+ tint_symbol_12(buffer, (offset + 16u), value[2u]);
+ tint_symbol_12(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f16>) {
+ tint_symbol_16(buffer, (offset + 0u), value[0u]);
+ tint_symbol_16(buffer, (offset + 8u), value[1u]);
+ tint_symbol_16(buffer, (offset + 16u), value[2u]);
+ tint_symbol_16(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
var array = value;
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ tint_symbol_9(buffer, (offset + (i * 16u)), array[i]);
+ }
+}
+
+fn tint_symbol_36(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<mat4x2<f16>, 2u>) {
+ var array_1 = value;
for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- tint_symbol_9(buffer, (offset + (i_1 * 16u)), array[i_1]);
+ tint_symbol_32(buffer, (offset + (i_1 * 16u)), array_1[i_1]);
}
}
fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : SB) {
- tint_symbol_1(buffer, (offset + 0u), value.a);
- tint_symbol_2(buffer, (offset + 4u), value.b);
- tint_symbol_3(buffer, (offset + 8u), value.c);
- tint_symbol_4(buffer, (offset + 16u), value.d);
- tint_symbol_5(buffer, (offset + 24u), value.e);
- tint_symbol_6(buffer, (offset + 32u), value.f);
- tint_symbol_7(buffer, (offset + 48u), value.g);
- tint_symbol_8(buffer, (offset + 64u), value.h);
- tint_symbol_9(buffer, (offset + 80u), value.i);
- tint_symbol_10(buffer, (offset + 96u), value.j);
- tint_symbol_11(buffer, (offset + 112u), value.k);
- tint_symbol_12(buffer, (offset + 128u), value.l);
- tint_symbol_13(buffer, (offset + 144u), value.m);
- tint_symbol_14(buffer, (offset + 160u), value.n);
- tint_symbol_15(buffer, (offset + 192u), value.o);
- tint_symbol_16(buffer, (offset + 224u), value.p);
- tint_symbol_17(buffer, (offset + 256u), value.q);
- tint_symbol_18(buffer, (offset + 304u), value.r);
- tint_symbol_19(buffer, (offset + 352u), value.s);
- tint_symbol_20(buffer, (offset + 384u), value.t);
- tint_symbol_21(buffer, (offset + 448u), value.u);
- tint_symbol_22(buffer, (offset + 512u), value.v);
+ tint_symbol_1(buffer, (offset + 0u), value.scalar_f32);
+ tint_symbol_2(buffer, (offset + 4u), value.scalar_i32);
+ tint_symbol_3(buffer, (offset + 8u), value.scalar_u32);
+ tint_symbol_4(buffer, (offset + 12u), value.scalar_f16);
+ tint_symbol_5(buffer, (offset + 16u), value.vec2_f32);
+ tint_symbol_6(buffer, (offset + 24u), value.vec2_i32);
+ tint_symbol_7(buffer, (offset + 32u), value.vec2_u32);
+ tint_symbol_8(buffer, (offset + 40u), value.vec2_f16);
+ tint_symbol_9(buffer, (offset + 48u), value.vec3_f32);
+ tint_symbol_10(buffer, (offset + 64u), value.vec3_i32);
+ tint_symbol_11(buffer, (offset + 80u), value.vec3_u32);
+ tint_symbol_12(buffer, (offset + 96u), value.vec3_f16);
+ tint_symbol_13(buffer, (offset + 112u), value.vec4_f32);
+ tint_symbol_14(buffer, (offset + 128u), value.vec4_i32);
+ tint_symbol_15(buffer, (offset + 144u), value.vec4_u32);
+ tint_symbol_16(buffer, (offset + 160u), value.vec4_f16);
+ tint_symbol_17(buffer, (offset + 168u), value.mat2x2_f32);
+ tint_symbol_18(buffer, (offset + 192u), value.mat2x3_f32);
+ tint_symbol_19(buffer, (offset + 224u), value.mat2x4_f32);
+ tint_symbol_20(buffer, (offset + 256u), value.mat3x2_f32);
+ tint_symbol_21(buffer, (offset + 288u), value.mat3x3_f32);
+ tint_symbol_22(buffer, (offset + 336u), value.mat3x4_f32);
+ tint_symbol_23(buffer, (offset + 384u), value.mat4x2_f32);
+ tint_symbol_24(buffer, (offset + 416u), value.mat4x3_f32);
+ tint_symbol_25(buffer, (offset + 480u), value.mat4x4_f32);
+ tint_symbol_26(buffer, (offset + 544u), value.mat2x2_f16);
+ tint_symbol_27(buffer, (offset + 552u), value.mat2x3_f16);
+ tint_symbol_28(buffer, (offset + 568u), value.mat2x4_f16);
+ tint_symbol_29(buffer, (offset + 584u), value.mat3x2_f16);
+ tint_symbol_30(buffer, (offset + 600u), value.mat3x3_f16);
+ tint_symbol_31(buffer, (offset + 624u), value.mat3x4_f16);
+ tint_symbol_32(buffer, (offset + 648u), value.mat4x2_f16);
+ tint_symbol_33(buffer, (offset + 664u), value.mat4x3_f16);
+ tint_symbol_34(buffer, (offset + 696u), value.mat4x4_f16);
+ tint_symbol_35(buffer, (offset + 736u), value.arr2_vec3_f32);
+ tint_symbol_36(buffer, (offset + 768u), value.arr2_mat4x2_f16);
}
@compute @workgroup_size(1)
@@ -1773,6 +2798,8 @@
TEST_F(DecomposeMemoryAccessTest, StoreStructure_OutOfOrder) {
auto* src = R"(
+enable f16;
+
@compute @workgroup_size(1)
fn main() {
sb = SB();
@@ -1781,152 +2808,255 @@
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
};
)";
auto* expect = R"(
-@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
-
-@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
+enable f16;
@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
+fn tint_symbol_1(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f32)
-@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
+@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : i32)
-@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : u32)
+
+@internal(intrinsic_store_storage_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : f16)
@internal(intrinsic_store_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
+fn tint_symbol_5(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f32>)
-@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
+@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<i32>)
-@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<u32>)
+
+@internal(intrinsic_store_storage_vec2_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec2<f16>)
@internal(intrinsic_store_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
fn tint_symbol_9(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f32>)
-@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<i32>)
-@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<u32>)
+
+@internal(intrinsic_store_storage_vec3_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec3<f16>)
@internal(intrinsic_store_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
-fn tint_symbol_12(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
+fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f32>)
-fn tint_symbol_13(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
- tint_symbol_6(buffer, (offset + 0u), value[0u]);
- tint_symbol_6(buffer, (offset + 8u), value[1u]);
+@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<i32>)
+
+@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<u32>)
+
+@internal(intrinsic_store_storage_vec4_f16) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : vec4<f16>)
+
+fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f32>) {
+ tint_symbol_5(buffer, (offset + 0u), value[0u]);
+ tint_symbol_5(buffer, (offset + 8u), value[1u]);
}
-fn tint_symbol_14(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
+fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f32>) {
tint_symbol_9(buffer, (offset + 0u), value[0u]);
tint_symbol_9(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_15(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
- tint_symbol_12(buffer, (offset + 0u), value[0u]);
- tint_symbol_12(buffer, (offset + 16u), value[1u]);
+fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f32>) {
+ tint_symbol_13(buffer, (offset + 0u), value[0u]);
+ tint_symbol_13(buffer, (offset + 16u), value[1u]);
}
-fn tint_symbol_16(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
- tint_symbol_6(buffer, (offset + 0u), value[0u]);
- tint_symbol_6(buffer, (offset + 8u), value[1u]);
- tint_symbol_6(buffer, (offset + 16u), value[2u]);
+fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f32>) {
+ tint_symbol_5(buffer, (offset + 0u), value[0u]);
+ tint_symbol_5(buffer, (offset + 8u), value[1u]);
+ tint_symbol_5(buffer, (offset + 16u), value[2u]);
}
-fn tint_symbol_17(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
+fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f32>) {
tint_symbol_9(buffer, (offset + 0u), value[0u]);
tint_symbol_9(buffer, (offset + 16u), value[1u]);
tint_symbol_9(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_18(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
- tint_symbol_12(buffer, (offset + 0u), value[0u]);
- tint_symbol_12(buffer, (offset + 16u), value[1u]);
- tint_symbol_12(buffer, (offset + 32u), value[2u]);
+fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f32>) {
+ tint_symbol_13(buffer, (offset + 0u), value[0u]);
+ tint_symbol_13(buffer, (offset + 16u), value[1u]);
+ tint_symbol_13(buffer, (offset + 32u), value[2u]);
}
-fn tint_symbol_19(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
- tint_symbol_6(buffer, (offset + 0u), value[0u]);
- tint_symbol_6(buffer, (offset + 8u), value[1u]);
- tint_symbol_6(buffer, (offset + 16u), value[2u]);
- tint_symbol_6(buffer, (offset + 24u), value[3u]);
+fn tint_symbol_23(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f32>) {
+ tint_symbol_5(buffer, (offset + 0u), value[0u]);
+ tint_symbol_5(buffer, (offset + 8u), value[1u]);
+ tint_symbol_5(buffer, (offset + 16u), value[2u]);
+ tint_symbol_5(buffer, (offset + 24u), value[3u]);
}
-fn tint_symbol_20(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
+fn tint_symbol_24(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f32>) {
tint_symbol_9(buffer, (offset + 0u), value[0u]);
tint_symbol_9(buffer, (offset + 16u), value[1u]);
tint_symbol_9(buffer, (offset + 32u), value[2u]);
tint_symbol_9(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_21(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
- tint_symbol_12(buffer, (offset + 0u), value[0u]);
- tint_symbol_12(buffer, (offset + 16u), value[1u]);
- tint_symbol_12(buffer, (offset + 32u), value[2u]);
- tint_symbol_12(buffer, (offset + 48u), value[3u]);
+fn tint_symbol_25(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f32>) {
+ tint_symbol_13(buffer, (offset + 0u), value[0u]);
+ tint_symbol_13(buffer, (offset + 16u), value[1u]);
+ tint_symbol_13(buffer, (offset + 32u), value[2u]);
+ tint_symbol_13(buffer, (offset + 48u), value[3u]);
}
-fn tint_symbol_22(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
+fn tint_symbol_26(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x2<f16>) {
+ tint_symbol_8(buffer, (offset + 0u), value[0u]);
+ tint_symbol_8(buffer, (offset + 4u), value[1u]);
+}
+
+fn tint_symbol_27(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x3<f16>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_28(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat2x4<f16>) {
+ tint_symbol_16(buffer, (offset + 0u), value[0u]);
+ tint_symbol_16(buffer, (offset + 8u), value[1u]);
+}
+
+fn tint_symbol_29(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x2<f16>) {
+ tint_symbol_8(buffer, (offset + 0u), value[0u]);
+ tint_symbol_8(buffer, (offset + 4u), value[1u]);
+ tint_symbol_8(buffer, (offset + 8u), value[2u]);
+}
+
+fn tint_symbol_30(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x3<f16>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 8u), value[1u]);
+ tint_symbol_12(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_31(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat3x4<f16>) {
+ tint_symbol_16(buffer, (offset + 0u), value[0u]);
+ tint_symbol_16(buffer, (offset + 8u), value[1u]);
+ tint_symbol_16(buffer, (offset + 16u), value[2u]);
+}
+
+fn tint_symbol_32(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x2<f16>) {
+ tint_symbol_8(buffer, (offset + 0u), value[0u]);
+ tint_symbol_8(buffer, (offset + 4u), value[1u]);
+ tint_symbol_8(buffer, (offset + 8u), value[2u]);
+ tint_symbol_8(buffer, (offset + 12u), value[3u]);
+}
+
+fn tint_symbol_33(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x3<f16>) {
+ tint_symbol_12(buffer, (offset + 0u), value[0u]);
+ tint_symbol_12(buffer, (offset + 8u), value[1u]);
+ tint_symbol_12(buffer, (offset + 16u), value[2u]);
+ tint_symbol_12(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_34(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : mat4x4<f16>) {
+ tint_symbol_16(buffer, (offset + 0u), value[0u]);
+ tint_symbol_16(buffer, (offset + 8u), value[1u]);
+ tint_symbol_16(buffer, (offset + 16u), value[2u]);
+ tint_symbol_16(buffer, (offset + 24u), value[3u]);
+}
+
+fn tint_symbol_35(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<vec3<f32>, 2u>) {
var array = value;
+ for(var i = 0u; (i < 2u); i = (i + 1u)) {
+ tint_symbol_9(buffer, (offset + (i * 16u)), array[i]);
+ }
+}
+
+fn tint_symbol_36(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : array<mat4x2<f16>, 2u>) {
+ var array_1 = value;
for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
- tint_symbol_9(buffer, (offset + (i_1 * 16u)), array[i_1]);
+ tint_symbol_32(buffer, (offset + (i_1 * 16u)), array_1[i_1]);
}
}
fn tint_symbol(@internal(disable_validation__function_parameter) buffer : ptr<storage, SB, read_write>, offset : u32, value : SB) {
- tint_symbol_1(buffer, (offset + 0u), value.a);
- tint_symbol_2(buffer, (offset + 4u), value.b);
- tint_symbol_3(buffer, (offset + 8u), value.c);
- tint_symbol_4(buffer, (offset + 16u), value.d);
- tint_symbol_5(buffer, (offset + 24u), value.e);
- tint_symbol_6(buffer, (offset + 32u), value.f);
- tint_symbol_7(buffer, (offset + 48u), value.g);
- tint_symbol_8(buffer, (offset + 64u), value.h);
- tint_symbol_9(buffer, (offset + 80u), value.i);
- tint_symbol_10(buffer, (offset + 96u), value.j);
- tint_symbol_11(buffer, (offset + 112u), value.k);
- tint_symbol_12(buffer, (offset + 128u), value.l);
- tint_symbol_13(buffer, (offset + 144u), value.m);
- tint_symbol_14(buffer, (offset + 160u), value.n);
- tint_symbol_15(buffer, (offset + 192u), value.o);
- tint_symbol_16(buffer, (offset + 224u), value.p);
- tint_symbol_17(buffer, (offset + 256u), value.q);
- tint_symbol_18(buffer, (offset + 304u), value.r);
- tint_symbol_19(buffer, (offset + 352u), value.s);
- tint_symbol_20(buffer, (offset + 384u), value.t);
- tint_symbol_21(buffer, (offset + 448u), value.u);
- tint_symbol_22(buffer, (offset + 512u), value.v);
+ tint_symbol_1(buffer, (offset + 0u), value.scalar_f32);
+ tint_symbol_2(buffer, (offset + 4u), value.scalar_i32);
+ tint_symbol_3(buffer, (offset + 8u), value.scalar_u32);
+ tint_symbol_4(buffer, (offset + 12u), value.scalar_f16);
+ tint_symbol_5(buffer, (offset + 16u), value.vec2_f32);
+ tint_symbol_6(buffer, (offset + 24u), value.vec2_i32);
+ tint_symbol_7(buffer, (offset + 32u), value.vec2_u32);
+ tint_symbol_8(buffer, (offset + 40u), value.vec2_f16);
+ tint_symbol_9(buffer, (offset + 48u), value.vec3_f32);
+ tint_symbol_10(buffer, (offset + 64u), value.vec3_i32);
+ tint_symbol_11(buffer, (offset + 80u), value.vec3_u32);
+ tint_symbol_12(buffer, (offset + 96u), value.vec3_f16);
+ tint_symbol_13(buffer, (offset + 112u), value.vec4_f32);
+ tint_symbol_14(buffer, (offset + 128u), value.vec4_i32);
+ tint_symbol_15(buffer, (offset + 144u), value.vec4_u32);
+ tint_symbol_16(buffer, (offset + 160u), value.vec4_f16);
+ tint_symbol_17(buffer, (offset + 168u), value.mat2x2_f32);
+ tint_symbol_18(buffer, (offset + 192u), value.mat2x3_f32);
+ tint_symbol_19(buffer, (offset + 224u), value.mat2x4_f32);
+ tint_symbol_20(buffer, (offset + 256u), value.mat3x2_f32);
+ tint_symbol_21(buffer, (offset + 288u), value.mat3x3_f32);
+ tint_symbol_22(buffer, (offset + 336u), value.mat3x4_f32);
+ tint_symbol_23(buffer, (offset + 384u), value.mat4x2_f32);
+ tint_symbol_24(buffer, (offset + 416u), value.mat4x3_f32);
+ tint_symbol_25(buffer, (offset + 480u), value.mat4x4_f32);
+ tint_symbol_26(buffer, (offset + 544u), value.mat2x2_f16);
+ tint_symbol_27(buffer, (offset + 552u), value.mat2x3_f16);
+ tint_symbol_28(buffer, (offset + 568u), value.mat2x4_f16);
+ tint_symbol_29(buffer, (offset + 584u), value.mat3x2_f16);
+ tint_symbol_30(buffer, (offset + 600u), value.mat3x3_f16);
+ tint_symbol_31(buffer, (offset + 624u), value.mat3x4_f16);
+ tint_symbol_32(buffer, (offset + 648u), value.mat4x2_f16);
+ tint_symbol_33(buffer, (offset + 664u), value.mat4x3_f16);
+ tint_symbol_34(buffer, (offset + 696u), value.mat4x4_f16);
+ tint_symbol_35(buffer, (offset + 736u), value.arr2_vec3_f32);
+ tint_symbol_36(buffer, (offset + 768u), value.arr2_mat4x2_f16);
}
@compute @workgroup_size(1)
@@ -1937,28 +3067,42 @@
@group(0) @binding(0) var<storage, read_write> sb : SB;
struct SB {
- a : i32,
- b : u32,
- c : f32,
- d : vec2<i32>,
- e : vec2<u32>,
- f : vec2<f32>,
- g : vec3<i32>,
- h : vec3<u32>,
- i : vec3<f32>,
- j : vec4<i32>,
- k : vec4<u32>,
- l : vec4<f32>,
- m : mat2x2<f32>,
- n : mat2x3<f32>,
- o : mat2x4<f32>,
- p : mat3x2<f32>,
- q : mat3x3<f32>,
- r : mat3x4<f32>,
- s : mat4x2<f32>,
- t : mat4x3<f32>,
- u : mat4x4<f32>,
- v : array<vec3<f32>, 2>,
+ scalar_f32 : f32,
+ scalar_i32 : i32,
+ scalar_u32 : u32,
+ scalar_f16 : f16,
+ vec2_f32 : vec2<f32>,
+ vec2_i32 : vec2<i32>,
+ vec2_u32 : vec2<u32>,
+ vec2_f16 : vec2<f16>,
+ vec3_f32 : vec3<f32>,
+ vec3_i32 : vec3<i32>,
+ vec3_u32 : vec3<u32>,
+ vec3_f16 : vec3<f16>,
+ vec4_f32 : vec4<f32>,
+ vec4_i32 : vec4<i32>,
+ vec4_u32 : vec4<u32>,
+ vec4_f16 : vec4<f16>,
+ mat2x2_f32 : mat2x2<f32>,
+ mat2x3_f32 : mat2x3<f32>,
+ mat2x4_f32 : mat2x4<f32>,
+ mat3x2_f32 : mat3x2<f32>,
+ mat3x3_f32 : mat3x3<f32>,
+ mat3x4_f32 : mat3x4<f32>,
+ mat4x2_f32 : mat4x2<f32>,
+ mat4x3_f32 : mat4x3<f32>,
+ mat4x4_f32 : mat4x4<f32>,
+ mat2x2_f16 : mat2x2<f16>,
+ mat2x3_f16 : mat2x3<f16>,
+ mat2x4_f16 : mat2x4<f16>,
+ mat3x2_f16 : mat3x2<f16>,
+ mat3x3_f16 : mat3x3<f16>,
+ mat3x4_f16 : mat3x4<f16>,
+ mat4x2_f16 : mat4x2<f16>,
+ mat4x3_f16 : mat4x3<f16>,
+ mat4x4_f16 : mat4x4<f16>,
+ arr2_vec3_f32 : array<vec3<f32>, 2>,
+ arr2_mat4x2_f16 : array<mat4x2<f16>, 2>,
}
)";
diff --git a/src/tint/transform/decompose_strided_matrix.cc b/src/tint/transform/decompose_strided_matrix.cc
index 5494ca2..b7fd7c2 100644
--- a/src/tint/transform/decompose_strided_matrix.cc
+++ b/src/tint/transform/decompose_strided_matrix.cc
@@ -129,7 +129,7 @@
std::unordered_map<MatrixInfo, Symbol, MatrixInfo::Hasher> mat_to_arr;
ctx.ReplaceAll([&](const ast::AssignmentStatement* stmt) -> const ast::Statement* {
if (auto* access = src->Sem().Get<sem::StructMemberAccess>(stmt->lhs)) {
- if (auto* info = decomposed.Find(access->Member()->Declaration())) {
+ if (auto info = decomposed.Find(access->Member()->Declaration())) {
auto fn = utils::GetOrCreate(mat_to_arr, *info, [&] {
auto name =
b.Symbols().New("mat" + std::to_string(info->matrix->columns()) + "x" +
@@ -168,7 +168,7 @@
std::unordered_map<MatrixInfo, Symbol, MatrixInfo::Hasher> arr_to_mat;
ctx.ReplaceAll([&](const ast::MemberAccessorExpression* expr) -> const ast::Expression* {
if (auto* access = src->Sem().Get<sem::StructMemberAccess>(expr)) {
- if (auto* info = decomposed.Find(access->Member()->Declaration())) {
+ if (auto info = decomposed.Find(access->Member()->Declaration())) {
auto fn = utils::GetOrCreate(arr_to_mat, *info, [&] {
auto name =
b.Symbols().New("arr_to_mat" + std::to_string(info->matrix->columns()) +
diff --git a/src/tint/transform/promote_initializers_to_let.cc b/src/tint/transform/promote_initializers_to_let.cc
index 9e02c45..7d81989 100644
--- a/src/tint/transform/promote_initializers_to_let.cc
+++ b/src/tint/transform/promote_initializers_to_let.cc
@@ -70,7 +70,8 @@
}
any_promoted = true;
- return hoist_to_decl_before.Add(expr, expr->Declaration(), true);
+ return hoist_to_decl_before.Add(expr, expr->Declaration(),
+ HoistToDeclBefore::VariableKind::kLet);
};
for (auto* node : src->ASTNodes().Objects()) {
diff --git a/src/tint/transform/simplify_pointers.cc b/src/tint/transform/simplify_pointers.cc
index b2b99ed..a0855b7 100644
--- a/src/tint/transform/simplify_pointers.cc
+++ b/src/tint/transform/simplify_pointers.cc
@@ -140,7 +140,7 @@
// variable identifier.
ctx.ReplaceAll([&](const ast::Expression* expr) -> const ast::Expression* {
// Look to see if we need to swap this Expression with a saved variable.
- if (auto* saved_var = saved_vars.Find(expr)) {
+ if (auto saved_var = saved_vars.Find(expr)) {
return ctx.dst->Expr(*saved_var);
}
diff --git a/src/tint/transform/std140.cc b/src/tint/transform/std140.cc
index 2116b0f..a371f24 100644
--- a/src/tint/transform/std140.cc
+++ b/src/tint/transform/std140.cc
@@ -265,8 +265,8 @@
};
/// @returns true if the given matrix needs decomposing to column vectors for std140 layout.
- /// TODO(crbug.com/tint/1502): This may need adjusting for `f16` matrices.
- static bool MatrixNeedsDecomposing(const sem::Matrix* mat) { return mat->ColumnStride() == 8; }
+ /// Std140 layout require matrix stride to be 16, otherwise decomposing is needed.
+ static bool MatrixNeedsDecomposing(const sem::Matrix* mat) { return mat->ColumnStride() != 16; }
/// ForkTypes walks the user-declared types in dependency order, forking structures that are
/// used as uniform buffers which (transitively) use matrices that need std140 decomposition to
@@ -401,7 +401,7 @@
return Switch(
ty, //
[&](const sem::Struct* str) -> const ast::Type* {
- if (auto* std140 = std140_structs.Find(str)) {
+ if (auto std140 = std140_structs.Find(str)) {
return b.create<ast::TypeName>(*std140);
}
return nullptr;
@@ -474,7 +474,7 @@
// natural size for the matrix. This extra padding needs to be
// applied to the last column vector.
attributes.Push(
- b.MemberSize(AInt(size - mat->ColumnType()->Size() * (num_columns - 1))));
+ b.MemberSize(AInt(size - mat->ColumnType()->Align() * (num_columns - 1))));
}
// Build the member
@@ -645,7 +645,8 @@
return "mat" + std::to_string(mat->columns()) + "x" + std::to_string(mat->rows()) +
"_" + ConvertSuffix(mat->type());
},
- [&](const sem::F32*) { return "f32"; },
+ [&](const sem::F32*) { return "f32"; }, //
+ [&](const sem::F16*) { return "f16"; },
[&](Default) {
TINT_ICE(Transform, b.Diagnostics())
<< "unhandled type for conversion name: " << src->FriendlyName(ty);
@@ -695,7 +696,7 @@
// call, or by reassembling a std140 matrix from column vector members.
utils::Vector<const ast::Expression*, 8> args;
for (auto* member : str->Members()) {
- if (auto* col_members = std140_mat_members.Find(member)) {
+ if (auto col_members = std140_mat_members.Find(member)) {
// std140 decomposed matrix. Reassemble.
auto* mat_ty = CreateASTTypeFor(ctx, member->Type());
auto mat_args =
diff --git a/src/tint/transform/std140.h b/src/tint/transform/std140.h
index 49e663d..769932f 100644
--- a/src/tint/transform/std140.h
+++ b/src/tint/transform/std140.h
@@ -20,11 +20,12 @@
namespace tint::transform {
/// Std140 is a transform that forks types used in the uniform address space that contain
-/// `matNx2<f32>` matrices into `N`x`vec2<f32>` column vectors. Types that transitively use these
-/// forked types are also forked. `var<uniform>` variables will use these forked types, and
-/// expressions loading from these variables will do appropriate conversions to the regular WGSL
-/// types. As `matNx2<f32>` matrices are the only type that violate std140-layout, this
-/// transformation is sufficient to have any WGSL structure be std140-layout conformant.
+/// `matNx2<f32>` matrices into `N`x`vec2<f32>` column vectors, and `matNxM<f16>` matrices into
+/// `N`x`vecM<f16>` column vectors. Types that transitively use these forked types are also forked.
+/// `var<uniform>` variables will use these forked types, and expressions loading from these
+/// variables will do appropriate conversions to the regular WGSL types. As `matNx2<f32>` and
+/// `matNxM<f16>` matrices are the only type that violate std140-layout, this transformation is
+/// sufficient to have any WGSL structure be std140-layout conformant.
///
/// @note This transform requires the PromoteSideEffectsToDecl transform to have been run first.
class Std140 final : public Castable<Std140, Transform> {
diff --git a/src/tint/transform/std140_exhaustive_test.cc b/src/tint/transform/std140_exhaustive_test.cc
index 01d2dae..f50e1c4 100644
--- a/src/tint/transform/std140_exhaustive_test.cc
+++ b/src/tint/transform/std140_exhaustive_test.cc
@@ -2838,6 +2838,15 @@
{4, 2, MatrixType::f32},
{4, 3, MatrixType::f32},
{4, 4, MatrixType::f32},
+ {2, 2, MatrixType::f16},
+ {2, 3, MatrixType::f16},
+ {2, 4, MatrixType::f16},
+ {3, 2, MatrixType::f16},
+ {3, 3, MatrixType::f16},
+ {3, 4, MatrixType::f16},
+ {4, 2, MatrixType::f16},
+ {4, 3, MatrixType::f16},
+ {4, 4, MatrixType::f16},
}));
using Std140Test_MatrixArray = TransformTestWithParam<MatrixCase>;
@@ -4866,6 +4875,15 @@
{4, 2, MatrixType::f32},
{4, 3, MatrixType::f32},
{4, 4, MatrixType::f32},
+ {2, 2, MatrixType::f16},
+ {2, 3, MatrixType::f16},
+ {2, 4, MatrixType::f16},
+ {3, 2, MatrixType::f16},
+ {3, 3, MatrixType::f16},
+ {3, 4, MatrixType::f16},
+ {4, 2, MatrixType::f16},
+ {4, 3, MatrixType::f16},
+ {4, 4, MatrixType::f16},
}));
} // namespace
diff --git a/src/tint/transform/std140_f16_test.cc b/src/tint/transform/std140_f16_test.cc
new file mode 100644
index 0000000..898bb73
--- /dev/null
+++ b/src/tint/transform/std140_f16_test.cc
@@ -0,0 +1,3596 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/transform/std140.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "src/tint/transform/test_helper.h"
+#include "src/tint/utils/string.h"
+
+namespace tint::transform {
+namespace {
+
+using Std140Test_F16 = TransformTest;
+
+TEST_F(Std140Test_F16, StructMatricesUniform) {
+ auto* src = R"(
+enable f16;
+
+struct S2x2F16 {
+ m : mat2x2<f16>,
+}
+struct S3x2F16 {
+ m : mat3x2<f16>,
+}
+struct S4x2F16 {
+ m : mat4x2<f16>,
+}
+struct S2x3F16 {
+ m : mat2x3<f16>,
+}
+struct S3x3F16 {
+ m : mat3x3<f16>,
+}
+struct S4x3F16 {
+ m : mat4x3<f16>,
+}
+struct S2x4F16 {
+ m : mat2x4<f16>,
+}
+struct S3x4F16 {
+ m : mat3x4<f16>,
+}
+struct S4x4F16 {
+ m : mat4x4<f16>,
+}
+
+@group(2) @binding(2) var<uniform> s2x2f16 : S2x2F16;
+@group(3) @binding(2) var<uniform> s3x2f16 : S3x2F16;
+@group(4) @binding(2) var<uniform> s4x2f16 : S4x2F16;
+@group(2) @binding(3) var<uniform> s2x3f16 : S2x3F16;
+@group(3) @binding(3) var<uniform> s3x3f16 : S3x3F16;
+@group(4) @binding(3) var<uniform> s4x3f16 : S4x3F16;
+@group(2) @binding(4) var<uniform> s2x4f16 : S2x4F16;
+@group(3) @binding(4) var<uniform> s3x4f16 : S3x4F16;
+@group(4) @binding(4) var<uniform> s4x4f16 : S4x4F16;
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S2x2F16 {
+ m : mat2x2<f16>,
+}
+
+struct S2x2F16_std140 {
+ m_0 : vec2<f16>,
+ m_1 : vec2<f16>,
+}
+
+struct S3x2F16 {
+ m : mat3x2<f16>,
+}
+
+struct S3x2F16_std140 {
+ m_0 : vec2<f16>,
+ m_1 : vec2<f16>,
+ m_2 : vec2<f16>,
+}
+
+struct S4x2F16 {
+ m : mat4x2<f16>,
+}
+
+struct S4x2F16_std140 {
+ m_0 : vec2<f16>,
+ m_1 : vec2<f16>,
+ m_2 : vec2<f16>,
+ m_3 : vec2<f16>,
+}
+
+struct S2x3F16 {
+ m : mat2x3<f16>,
+}
+
+struct S2x3F16_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+struct S3x3F16 {
+ m : mat3x3<f16>,
+}
+
+struct S3x3F16_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+ m_2 : vec3<f16>,
+}
+
+struct S4x3F16 {
+ m : mat4x3<f16>,
+}
+
+struct S4x3F16_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+ m_2 : vec3<f16>,
+ m_3 : vec3<f16>,
+}
+
+struct S2x4F16 {
+ m : mat2x4<f16>,
+}
+
+struct S2x4F16_std140 {
+ m_0 : vec4<f16>,
+ m_1 : vec4<f16>,
+}
+
+struct S3x4F16 {
+ m : mat3x4<f16>,
+}
+
+struct S3x4F16_std140 {
+ m_0 : vec4<f16>,
+ m_1 : vec4<f16>,
+ m_2 : vec4<f16>,
+}
+
+struct S4x4F16 {
+ m : mat4x4<f16>,
+}
+
+struct S4x4F16_std140 {
+ m_0 : vec4<f16>,
+ m_1 : vec4<f16>,
+ m_2 : vec4<f16>,
+ m_3 : vec4<f16>,
+}
+
+@group(2) @binding(2) var<uniform> s2x2f16 : S2x2F16_std140;
+
+@group(3) @binding(2) var<uniform> s3x2f16 : S3x2F16_std140;
+
+@group(4) @binding(2) var<uniform> s4x2f16 : S4x2F16_std140;
+
+@group(2) @binding(3) var<uniform> s2x3f16 : S2x3F16_std140;
+
+@group(3) @binding(3) var<uniform> s3x3f16 : S3x3F16_std140;
+
+@group(4) @binding(3) var<uniform> s4x3f16 : S4x3F16_std140;
+
+@group(2) @binding(4) var<uniform> s2x4f16 : S2x4F16_std140;
+
+@group(3) @binding(4) var<uniform> s3x4f16 : S3x4F16_std140;
+
+@group(4) @binding(4) var<uniform> s4x4f16 : S4x4F16_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+// In the following tests we only test `mat2x3<f16>`, and set all constant column index to 1, row
+// index 0, inner array index 2, and outer array index 3. For exhaustive tests, i.e. tests on all
+// matrix shape and different valid constant index, please refer to std140_exhaustive_test.cc
+
+TEST_F(Std140Test_F16, SingleStructMatUniform_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, CustomAlign_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ before : i32,
+ @align(128)
+ m : mat2x3<f16>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ before : i32,
+ @align(128)
+ m : mat2x3<f16>,
+ after : i32,
+}
+
+struct S_std140 {
+ before : i32,
+ @align(128i)
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, CustomSizeMat_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ before : i32,
+ @size(128)
+ m : mat2x3<f16>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ before : i32,
+ @size(128)
+ m : mat2x3<f16>,
+ after : i32,
+}
+
+struct S_std140 {
+ before : i32,
+ m_0 : vec3<f16>,
+ @size(120)
+ m_1 : vec3<f16>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, CustomAlignAndSize_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ before : i32,
+ @align(128) @size(128)
+ m : mat2x3<f16>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ before : i32,
+ @align(128) @size(128)
+ m : mat2x3<f16>,
+ after : i32,
+}
+
+struct S_std140 {
+ before : i32,
+ @align(128i)
+ m_0 : vec3<f16>,
+ @size(120)
+ m_1 : vec3<f16>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatrixUsageInForLoop_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ for(var i = u32(s.m[0][0]); (i < u32(s.m[i][1])); i += u32(s.m[1][i])) {
+ }
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0_1(p0 : u32) -> f16 {
+ switch(p0) {
+ case 0u: {
+ return s.m_0[1u];
+ }
+ case 1u: {
+ return s.m_1[1u];
+ }
+ default: {
+ return f16();
+ }
+ }
+}
+
+fn f() {
+ for(var i = u32(s.m_0[0u]); (i < u32(load_s_m_p0_1(u32(i)))); i += u32(s.m_1[i])) {
+ }
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadMatrix_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> m : mat2x3<f16>;
+
+fn f() {
+ let l = m;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> m : mat2x3_f16;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let l = conv_mat2x3_f16(m);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadColumn_ConstIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let l = a[1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn f() {
+ let l = a.col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadColumn_VariableIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn load_a_p0(p0 : u32) -> vec3<f16> {
+ switch(p0) {
+ case 0u: {
+ return a.col0;
+ }
+ case 1u: {
+ return a.col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadColumnSwizzle_ConstIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let l = a[1].yzx;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn f() {
+ let l = a.col1.yzx;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadColumnSwizzle_VariableIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].yzx;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn load_a_p0_yzx(p0 : u32) -> vec3<f16> {
+ switch(p0) {
+ case 0u: {
+ return a.col0.yzx;
+ }
+ case 1u: {
+ return a.col1.yzx;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_yzx(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let l = a[1][0];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn f() {
+ let l = a.col1[0u];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let I = 0;
+ let l = a[I][0];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn load_a_p0_0(p0 : u32) -> f16 {
+ switch(p0) {
+ case 0u: {
+ return a.col0[0u];
+ }
+ case 1u: {
+ return a.col1[0u];
+ }
+ default: {
+ return f16();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_a_p0_0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let I = 0;
+ let l = a[1][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn f() {
+ let I = 0;
+ let l = a.col1[I];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, MatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : mat2x3<f16>;
+
+fn f() {
+ let I = 0;
+ let l = a[I][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat2x3_f16;
+
+fn load_a_p0_p1(p0 : u32, p1 : u32) -> f16 {
+ switch(p0) {
+ case 0u: {
+ return a.col0[p1];
+ }
+ case 1u: {
+ return a.col1[p1];
+ }
+ default: {
+ return f16();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_a_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_NameCollision_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m_1 : i32,
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m_1 : i32,
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_1 : i32,
+ m__0 : vec3<f16>,
+ m__1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadStruct_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn f() {
+ let l = conv_S(s);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadMatrix_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.m;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m() -> mat2x3<f16> {
+ let s = &(s);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn f() {
+ let l = load_s_m();
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadColumn_ConstIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.m[1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let l = s.m_1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadColumn_VariableIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0(p0 : u32) -> vec3<f16> {
+ switch(p0) {
+ case 0u: {
+ return s.m_0;
+ }
+ case 1u: {
+ return s.m_1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_s_m_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.m[1][0];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let l = s.m_1[0u];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[I][0];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0_0(p0 : u32) -> f16 {
+ switch(p0) {
+ case 0u: {
+ return s.m_0[0u];
+ }
+ case 1u: {
+ return s.m_1[0u];
+ }
+ default: {
+ return f16();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_s_m_p0_0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[1][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let I = 0;
+ let l = s.m_1[I];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructMatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[I][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0_p1(p0 : u32, p1 : u32) -> f16 {
+ switch(p0) {
+ case 0u: {
+ return s.m_0[p1];
+ }
+ case 1u: {
+ return s.m_1[p1];
+ }
+ default: {
+ return f16();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_s_m_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_LoadArray_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn conv_arr3_S(val : array<S_std140, 3u>) -> array<S, 3u> {
+ var arr : array<S, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_S(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_S(a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_LoadStruct_ConstIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a[2];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn f() {
+ let l = conv_S(a[2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_LoadStruct_VariableIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_S(a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_LoadMatrix_ConstArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a[2].m;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_2_m() -> mat2x3<f16> {
+ let s = &(a[2u]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn f() {
+ let l = load_a_2_m();
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_LoadMatrix_VariableArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_p0_m(p0 : u32) -> mat2x3<f16> {
+ let s = &(a[p0]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_m(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayStructMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a[2].m[1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn f() {
+ let l = a[2u].m_1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayStructMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m[1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m_1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayStructMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[2].m[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_2_m_p0(p0 : u32) -> vec3<f16> {
+ switch(p0) {
+ case 0u: {
+ return a[2u].m_0;
+ }
+ case 1u: {
+ return a[2u].m_1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_2_m_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayStructMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_p0_m_p1(p0 : u32, p1 : u32) -> vec3<f16> {
+ switch(p1) {
+ case 0u: {
+ return a[p0].m_0;
+ }
+ case 1u: {
+ return a[p0].m_1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_m_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructArrayStructMatUniform_Loads_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct Inner {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let l_a : array<Outer, 4> = a;
+ let l_a_1 : Outer = a[1];
+ let l_a_I : Outer = a[I];
+ let l_a_2_a : array<Inner, 4> = a[2].a;
+ let l_a_I_a : array<Inner, 4> = a[I].a;
+ let l_a_3_a_1 : Inner = a[3].a[1];
+ let l_a_3_a_I : Inner = a[3].a[I];
+ let l_a_I_a_1 : Inner = a[I].a[1];
+ let l_a_I_a_J : Inner = a[I].a[J];
+ let l_a_0_a_2_m : mat2x3<f16> = a[0].a[2].m;
+ let l_a_0_a_I_m : mat2x3<f16> = a[0].a[I].m;
+ let l_a_I_a_2_m : mat2x3<f16> = a[I].a[2].m;
+ let l_a_I_a_J_m : mat2x3<f16> = a[I].a[J].m;
+ let l_a_1_a_3_m_0 : vec3<f16> = a[1].a[3].m[0];
+ let l_a_I_a_J_m_K : vec3<f16> = a[I].a[J].m[K];
+ let l_a_2_a_0_m_1_0 : f16 = a[2].a[0].m[1][0];
+ let l_a_I_a_J_m_K_I : f16 = a[I].a[J].m[K][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct Inner {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct Inner_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+struct Outer_std140 {
+ a : array<Inner_std140, 4u>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
+
+fn conv_Inner(val : Inner_std140) -> Inner {
+ return Inner(mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
+ var arr : array<Inner, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Inner(val[i]);
+ }
+ return arr;
+}
+
+fn conv_Outer(val : Outer_std140) -> Outer {
+ return Outer(conv_arr4_Inner(val.a));
+}
+
+fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
+ var arr : array<Outer, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Outer(val[i]);
+ }
+ return arr;
+}
+
+fn load_a_0_a_2_m() -> mat2x3<f16> {
+ let s = &(a[0u].a[2u]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_0_a_p0_m(p0 : u32) -> mat2x3<f16> {
+ let s = &(a[0u].a[p0]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_p0_a_2_m(p0 : u32) -> mat2x3<f16> {
+ let s = &(a[p0].a[2u]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> mat2x3<f16> {
+ let s = &(a[p0].a[p1]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> vec3<f16> {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0;
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> f16 {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0[p3];
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1[p3];
+ }
+ default: {
+ return f16();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let l_a : array<Outer, 4> = conv_arr4_Outer(a);
+ let l_a_1 : Outer = conv_Outer(a[1u]);
+ let l_a_I : Outer = conv_Outer(a[I]);
+ let l_a_2_a : array<Inner, 4> = conv_arr4_Inner(a[2u].a);
+ let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
+ let l_a_3_a_1 : Inner = conv_Inner(a[3u].a[1u]);
+ let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
+ let l_a_I_a_1 : Inner = conv_Inner(a[I].a[1u]);
+ let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
+ let l_a_0_a_2_m : mat2x3<f16> = load_a_0_a_2_m();
+ let l_a_0_a_I_m : mat2x3<f16> = load_a_0_a_p0_m(u32(I));
+ let l_a_I_a_2_m : mat2x3<f16> = load_a_p0_a_2_m(u32(I));
+ let l_a_I_a_J_m : mat2x3<f16> = load_a_p0_a_p1_m(u32(I), u32(J));
+ let l_a_1_a_3_m_0 : vec3<f16> = a[1u].a[3u].m_0;
+ let l_a_I_a_J_m_K : vec3<f16> = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
+ let l_a_2_a_0_m_1_0 : f16 = a[2u].a[0u].m_1[0u];
+ let l_a_I_a_J_m_K_I : f16 = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructArrayStructMatUniform_LoadsViaPtrs_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct Inner {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let p_a = &(a);
+ let p_a_3 = &((*(p_a))[3]);
+ let p_a_I = &((*(p_a))[I]);
+ let p_a_3_a = &((*(p_a_3)).a);
+ let p_a_I_a = &((*(p_a_I)).a);
+ let p_a_3_a_2 = &((*(p_a_3_a))[2]);
+ let p_a_3_a_I = &((*(p_a_3_a))[I]);
+ let p_a_I_a_2 = &((*(p_a_I_a))[2]);
+ let p_a_I_a_J = &((*(p_a_I_a))[J]);
+ let p_a_3_a_2_m = &((*(p_a_3_a_2)).m);
+ let p_a_3_a_I_m = &((*(p_a_3_a_I)).m);
+ let p_a_I_a_2_m = &((*(p_a_I_a_2)).m);
+ let p_a_I_a_J_m = &((*(p_a_I_a_J)).m);
+ let p_a_3_a_2_m_1 = &((*(p_a_3_a_2_m))[1]);
+ let p_a_I_a_J_m_K = &((*(p_a_I_a_J_m))[K]);
+ let l_a : array<Outer, 4> = *(p_a);
+ let l_a_3 : Outer = *(p_a_3);
+ let l_a_I : Outer = *(p_a_I);
+ let l_a_3_a : array<Inner, 4> = *(p_a_3_a);
+ let l_a_I_a : array<Inner, 4> = *(p_a_I_a);
+ let l_a_3_a_2 : Inner = *(p_a_3_a_2);
+ let l_a_3_a_I : Inner = *(p_a_3_a_I);
+ let l_a_I_a_2 : Inner = *(p_a_I_a_2);
+ let l_a_I_a_J : Inner = *(p_a_I_a_J);
+ let l_a_3_a_2_m : mat2x3<f16> = *(p_a_3_a_2_m);
+ let l_a_3_a_I_m : mat2x3<f16> = *(p_a_3_a_I_m);
+ let l_a_I_a_2_m : mat2x3<f16> = *(p_a_I_a_2_m);
+ let l_a_I_a_J_m : mat2x3<f16> = *(p_a_I_a_J_m);
+ let l_a_3_a_2_m_1 : vec3<f16> = *(p_a_3_a_2_m_1);
+ let l_a_I_a_J_m_K : vec3<f16> = *(p_a_I_a_J_m_K);
+ let l_a_2_a_0_m_1_0 : f16 = (*(p_a_3_a_2_m_1))[0];
+ let l_a_I_a_J_m_K_I : f16 = (*(p_a_I_a_J_m_K))[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct Inner {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct Inner_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+struct Outer_std140 {
+ a : array<Inner_std140, 4u>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
+
+fn conv_Inner(val : Inner_std140) -> Inner {
+ return Inner(mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
+ var arr : array<Inner, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Inner(val[i]);
+ }
+ return arr;
+}
+
+fn conv_Outer(val : Outer_std140) -> Outer {
+ return Outer(conv_arr4_Inner(val.a));
+}
+
+fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
+ var arr : array<Outer, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Outer(val[i]);
+ }
+ return arr;
+}
+
+fn load_a_3_a_2_m() -> mat2x3<f16> {
+ let s = &(a[3u].a[2u]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_3_a_p0_m(p0 : u32) -> mat2x3<f16> {
+ let s = &(a[3u].a[p0]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_p0_a_2_m(p0 : u32) -> mat2x3<f16> {
+ let s = &(a[p0].a[2u]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> mat2x3<f16> {
+ let s = &(a[p0].a[p1]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> vec3<f16> {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0;
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> f16 {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0[p3];
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1[p3];
+ }
+ default: {
+ return f16();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let p_a = conv_arr4_Outer(a);
+ let p_a_3 = conv_Outer(a[3u]);
+ let p_a_I = conv_Outer(a[I]);
+ let p_a_3_a = conv_arr4_Inner(a[3u].a);
+ let p_a_I_a = conv_arr4_Inner(a[I].a);
+ let p_a_3_a_2 = conv_Inner(a[3u].a[2u]);
+ let p_a_3_a_I = conv_Inner(a[3u].a[I]);
+ let p_a_I_a_2 = conv_Inner(a[I].a[2u]);
+ let p_a_I_a_J = conv_Inner(a[I].a[J]);
+ let p_a_3_a_2_m = load_a_3_a_2_m();
+ let p_a_3_a_I_m = load_a_3_a_p0_m(u32(I));
+ let p_a_I_a_2_m = load_a_p0_a_2_m(u32(I));
+ let p_a_I_a_J_m = load_a_p0_a_p1_m(u32(I), u32(J));
+ let p_a_3_a_2_m_1 = a[3u].a[2u].m_1;
+ let p_a_I_a_J_m_K = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
+ let l_a : array<Outer, 4> = conv_arr4_Outer(a);
+ let l_a_3 : Outer = conv_Outer(a[3u]);
+ let l_a_I : Outer = conv_Outer(a[I]);
+ let l_a_3_a : array<Inner, 4> = conv_arr4_Inner(a[3u].a);
+ let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
+ let l_a_3_a_2 : Inner = conv_Inner(a[3u].a[2u]);
+ let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
+ let l_a_I_a_2 : Inner = conv_Inner(a[I].a[2u]);
+ let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
+ let l_a_3_a_2_m : mat2x3<f16> = load_a_3_a_2_m();
+ let l_a_3_a_I_m : mat2x3<f16> = load_a_3_a_p0_m(u32(I));
+ let l_a_I_a_2_m : mat2x3<f16> = load_a_p0_a_2_m(u32(I));
+ let l_a_I_a_J_m : mat2x3<f16> = load_a_p0_a_p1_m(u32(I), u32(J));
+ let l_a_3_a_2_m_1 : vec3<f16> = a[3u].a[2u].m_1;
+ let l_a_I_a_J_m_K : vec3<f16> = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
+ let l_a_2_a_0_m_1_0 : f16 = a[3u].a[2u].m_1[0u];
+ let l_a_I_a_J_m_K_I : f16 = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_CopyArray_UniformToStorage_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 4>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn f() {
+ s = u;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn conv_arr4_S(val : array<S_std140, 4u>) -> array<S, 4u> {
+ var arr : array<S, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_S(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ s = conv_arr4_S(u);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_CopyStruct_UniformToWorkgroup_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 4>;
+
+var<workgroup> w : array<S, 4>;
+
+fn f() {
+ w[0] = u[1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ v : vec4<i32>,
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
+
+var<workgroup> w : array<S, 4>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(val.v, mat2x3<f16>(val.m_0, val.m_1));
+}
+
+fn f() {
+ w[0] = conv_S(u[1u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_CopyMatrix_UniformToPrivate_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 3>;
+
+var<private> p : array<S, 4>;
+
+fn f() {
+ p[2].m = u[1].m;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ v : vec4<i32>,
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
+
+var<private> p : array<S, 4>;
+
+fn load_u_1_m() -> mat2x3<f16> {
+ let s = &(u[1u]);
+ return mat2x3<f16>((*(s)).m_0, (*(s)).m_1);
+}
+
+fn f() {
+ p[2].m = load_u_1_m();
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_CopyColumn_UniformToStorage_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 3>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn f() {
+ s[3].m[1] = u[2].m[0];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn f() {
+ s[3].m[1] = u[2u].m_0;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_CopyColumnSwizzle_UniformToWorkgroup_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 4>;
+
+var<workgroup> w : array<S, 4>;
+
+fn f() {
+ w[3].m[1] = u[2].m[0].yzx.yzx;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
+
+var<workgroup> w : array<S, 4>;
+
+fn f() {
+ w[3].m[1] = u[2u].m_0.yzx.yzx;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayStructMatUniform_CopyScalar_UniformToPrivate_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 3>;
+
+var<private> p : array<S, 4>;
+
+fn f() {
+ p[3].m[1].x = u[2].m[0].y;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat2x3<f16>,
+}
+
+struct S_std140 {
+ v : vec4<i32>,
+ m_0 : vec3<f16>,
+ @size(56)
+ m_1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
+
+var<private> p : array<S, 4>;
+
+fn f() {
+ p[3].m[1].x = u[2u].m_0[1u];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayMatUniform_LoadArray_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3<f16>, 3>;
+
+fn f() {
+ let l = a;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3_f16, 3u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x3_f16(val : array<mat2x3_f16, 3u>) -> array<mat2x3<f16>, 3u> {
+ var arr : array<mat2x3<f16>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x3_f16(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_mat2x3_f16(a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayMatUniform_LoadMatrix_ConstArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3<f16>, 3>;
+
+fn f() {
+ let l = a[2];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3_f16, 3u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let l = conv_mat2x3_f16(a[2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayMatUniform_LoadMatrix_VariableArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3<f16>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3_f16, 3u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x3_f16(a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3<f16>, 3>;
+
+fn f() {
+ let l = a[2][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3_f16, 3u>;
+
+fn f() {
+ let l = a[2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3<f16>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3_f16, 3u>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3<f16>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[2][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3_f16, 3u>;
+
+fn load_a_2_p0(p0 : u32) -> vec3<f16> {
+ switch(p0) {
+ case 0u: {
+ return a[2u].col0;
+ }
+ case 1u: {
+ return a[2u].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_2_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3<f16>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x3_f16, 3u>;
+
+fn load_a_p0_p1(p0 : u32, p1 : u32) -> vec3<f16> {
+ switch(p1) {
+ case 0u: {
+ return a[p0].col0;
+ }
+ case 1u: {
+ return a[p0].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructArrayMatUniform_LoadStruct_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x3_f16(val : array<mat2x3_f16, 3u>) -> array<mat2x3<f16>, 3u> {
+ var arr : array<mat2x3<f16>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x3_f16(val[i]);
+ }
+ return arr;
+}
+
+fn conv_S(val : S_std140) -> S {
+ return S(conv_arr3_mat2x3_f16(val.a));
+}
+
+fn f() {
+ let l = conv_S(s);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructArrayMatUniform_LoadArray_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.a;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x3_f16(val : array<mat2x3_f16, 3u>) -> array<mat2x3<f16>, 3u> {
+ var arr : array<mat2x3<f16>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x3_f16(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_mat2x3_f16(s.a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructArrayMatUniform_LoadMatrix_ConstArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.a[2];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let l = conv_mat2x3_f16(s.a[2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, StructArrayMatUniform_LoadMatrix_VariableArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x3_f16(s.a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ StructArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.a[2][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let l = s.a[2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ StructArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ StructArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[2][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_a_2_p0(p0 : u32) -> vec3<f16> {
+ switch(p0) {
+ case 0u: {
+ return s.a[2u].col0;
+ }
+ case 1u: {
+ return s.a[2u].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_s_a_2_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ StructArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+struct S {
+ a : array<mat2x3<f16>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x3_f16, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_a_p0_p1(p0 : u32, p1 : u32) -> vec3<f16> {
+ switch(p1) {
+ case 0u: {
+ return s.a[p0].col0;
+ }
+ case 1u: {
+ return s.a[p0].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_s_a_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayArrayMatUniform_LoadArrays_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let l = a;
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x3_f16(val : array<mat2x3_f16, 3u>) -> array<mat2x3<f16>, 3u> {
+ var arr : array<mat2x3<f16>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x3_f16(val[i]);
+ }
+ return arr;
+}
+
+fn conv_arr4_arr3_mat2x3_f16(val : array<array<mat2x3_f16, 3u>, 4u>) -> array<array<mat2x3<f16>, 3u>, 4u> {
+ var arr : array<array<mat2x3<f16>, 3u>, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_arr3_mat2x3_f16(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr4_arr3_mat2x3_f16(a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayArrayMatUniform_LoadArray_ConstOuterArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let l = a[3];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x3_f16(val : array<mat2x3_f16, 3u>) -> array<mat2x3<f16>, 3u> {
+ var arr : array<mat2x3<f16>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x3_f16(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_mat2x3_f16(a[3u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16, ArrayArrayMatUniform_LoadArray_VariableOuterArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x3_f16(val : array<mat2x3_f16, 3u>) -> array<mat2x3<f16>, 3u> {
+ var arr : array<mat2x3<f16>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x3_f16(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_arr3_mat2x3_f16(a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_ConstInnerArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let l = a[3][2];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let l = conv_mat2x3_f16(a[3u][2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_VariableInnerArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[3][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x3_f16(a[3u][I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_ConstInnerArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][2];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x3_f16(a[I][2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F16,
+ ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_VariableInnerArrayIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn conv_mat2x3_f16(val : mat2x3_f16) -> mat2x3<f16> {
+ return mat2x3<f16>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x3_f16(a[I][I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let l = a[3][2][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn f() {
+ let l = a[3u][2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[3][2][I];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn load_a_3_2_p0(p0 : u32) -> vec3<f16> {
+ switch(p0) {
+ case 0u: {
+ return a[3u][2u].col0;
+ }
+ case 1u: {
+ return a[3u][2u].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_3_2_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[3][I][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn f() {
+ let I = 1;
+ let l = a[3u][I].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[3][I][J];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn load_a_3_p0_p1(p0 : u32, p1 : u32) -> vec3<f16> {
+ switch(p1) {
+ case 0u: {
+ return a[3u][p0].col0;
+ }
+ case 1u: {
+ return a[3u][p0].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = load_a_3_p0_p1(u32(I), u32(J));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][2][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[I][2][J];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn load_a_p0_2_p1(p0 : u32, p1 : u32) -> vec3<f16> {
+ switch(p1) {
+ case 0u: {
+ return a[p0][2u].col0;
+ }
+ case 1u: {
+ return a[p0][2u].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = load_a_p0_2_p1(u32(I), u32(J));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[I][J][1];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[I][J].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F16,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex_Mat2x3F16) {
+ auto* src = R"(
+enable f16;
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3<f16>, 3>, 4>;
+
+fn f() {
+ let I = 0;
+ let J = 1;
+ let K = 2;
+ let l = a[I][J][K];
+}
+)";
+
+ auto* expect = R"(
+enable f16;
+
+struct mat2x3_f16 {
+ col0 : vec3<f16>,
+ col1 : vec3<f16>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x3_f16, 3u>, 4u>;
+
+fn load_a_p0_p1_p2(p0 : u32, p1 : u32, p2 : u32) -> vec3<f16> {
+ switch(p2) {
+ case 0u: {
+ return a[p0][p1].col0;
+ }
+ case 1u: {
+ return a[p0][p1].col1;
+ }
+ default: {
+ return vec3<f16>();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let J = 1;
+ let K = 2;
+ let l = load_a_p0_p1_p2(u32(I), u32(J), u32(K));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+} // namespace
+} // namespace tint::transform
diff --git a/src/tint/transform/std140_f32_test.cc b/src/tint/transform/std140_f32_test.cc
new file mode 100644
index 0000000..b0bd467
--- /dev/null
+++ b/src/tint/transform/std140_f32_test.cc
@@ -0,0 +1,3359 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/transform/std140.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "src/tint/transform/test_helper.h"
+#include "src/tint/utils/string.h"
+
+namespace tint::transform {
+namespace {
+
+using Std140Test_F32 = TransformTest;
+
+TEST_F(Std140Test_F32, StructMatricesUniform) {
+ auto* src = R"(
+struct S2x2F32 {
+ m : mat2x2<f32>,
+}
+struct S3x2F32 {
+ m : mat3x2<f32>,
+}
+struct S4x2F32 {
+ m : mat4x2<f32>,
+}
+struct S2x3F32 {
+ m : mat2x3<f32>,
+}
+struct S3x3F32 {
+ m : mat3x3<f32>,
+}
+struct S4x3F32 {
+ m : mat4x3<f32>,
+}
+struct S2x4F32 {
+ m : mat2x4<f32>,
+}
+struct S3x4F32 {
+ m : mat3x4<f32>,
+}
+struct S4x4F32 {
+ m : mat4x4<f32>,
+}
+
+@group(2) @binding(2) var<uniform> s2x2f32 : S2x2F32;
+@group(3) @binding(2) var<uniform> s3x2f32 : S3x2F32;
+@group(4) @binding(2) var<uniform> s4x2f32 : S4x2F32;
+@group(2) @binding(3) var<uniform> s2x3f32 : S2x3F32;
+@group(3) @binding(3) var<uniform> s3x3f32 : S3x3F32;
+@group(4) @binding(3) var<uniform> s4x3f32 : S4x3F32;
+@group(2) @binding(4) var<uniform> s2x4f32 : S2x4F32;
+@group(3) @binding(4) var<uniform> s3x4f32 : S3x4F32;
+@group(4) @binding(4) var<uniform> s4x4f32 : S4x4F32;
+)";
+
+ auto* expect = R"(
+struct S2x2F32 {
+ m : mat2x2<f32>,
+}
+
+struct S2x2F32_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+}
+
+struct S3x2F32 {
+ m : mat3x2<f32>,
+}
+
+struct S3x2F32_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+struct S4x2F32 {
+ m : mat4x2<f32>,
+}
+
+struct S4x2F32_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+ m_3 : vec2<f32>,
+}
+
+struct S2x3F32 {
+ m : mat2x3<f32>,
+}
+
+struct S3x3F32 {
+ m : mat3x3<f32>,
+}
+
+struct S4x3F32 {
+ m : mat4x3<f32>,
+}
+
+struct S2x4F32 {
+ m : mat2x4<f32>,
+}
+
+struct S3x4F32 {
+ m : mat3x4<f32>,
+}
+
+struct S4x4F32 {
+ m : mat4x4<f32>,
+}
+
+@group(2) @binding(2) var<uniform> s2x2f32 : S2x2F32_std140;
+
+@group(3) @binding(2) var<uniform> s3x2f32 : S3x2F32_std140;
+
+@group(4) @binding(2) var<uniform> s4x2f32 : S4x2F32_std140;
+
+@group(2) @binding(3) var<uniform> s2x3f32 : S2x3F32;
+
+@group(3) @binding(3) var<uniform> s3x3f32 : S3x3F32;
+
+@group(4) @binding(3) var<uniform> s4x3f32 : S4x3F32;
+
+@group(2) @binding(4) var<uniform> s2x4f32 : S2x4F32;
+
+@group(3) @binding(4) var<uniform> s3x4f32 : S3x4F32;
+
+@group(4) @binding(4) var<uniform> s4x4f32 : S4x4F32;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+// In the following tests we only test `mat2x2<f32>` for matrix used as array element type and
+// `mat3x2<f32>` otherwise, and set all constant column index to 1, row index 0, inner array index
+// 2, and outer array index 3. For exhaustive tests, i.e. tests on all matrix shape and different
+// valid constant index, please refer to std140_exhaustive_test.cc
+
+TEST_F(Std140Test_F32, SingleStructMatUniform_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, CustomAlign_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ before : i32,
+ @align(128)
+ m : mat3x2<f32>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+struct S {
+ before : i32,
+ @align(128)
+ m : mat3x2<f32>,
+ after : i32,
+}
+
+struct S_std140 {
+ before : i32,
+ @align(128i)
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, CustomSizeMat_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ before : i32,
+ @size(128)
+ m : mat3x2<f32>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+struct S {
+ before : i32,
+ @size(128)
+ m : mat3x2<f32>,
+ after : i32,
+}
+
+struct S_std140 {
+ before : i32,
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(112)
+ m_2 : vec2<f32>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, CustomAlignAndSize_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ before : i32,
+ @align(128) @size(128)
+ m : mat3x2<f32>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+struct S {
+ before : i32,
+ @align(128) @size(128)
+ m : mat3x2<f32>,
+ after : i32,
+}
+
+struct S_std140 {
+ before : i32,
+ @align(128i)
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(112)
+ m_2 : vec2<f32>,
+ after : i32,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatrixUsageInForLoop_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ for(var i = u32(s.m[0][0]); (i < u32(s.m[i][1])); i += u32(s.m[1][i])) {
+ }
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0_1(p0 : u32) -> f32 {
+ switch(p0) {
+ case 0u: {
+ return s.m_0[1u];
+ }
+ case 1u: {
+ return s.m_1[1u];
+ }
+ case 2u: {
+ return s.m_2[1u];
+ }
+ default: {
+ return f32();
+ }
+ }
+}
+
+fn f() {
+ for(var i = u32(s.m_0[0u]); (i < u32(load_s_m_p0_1(u32(i)))); i += u32(s.m_1[i])) {
+ }
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadMatrix_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> m : mat3x2<f32>;
+
+fn f() {
+ let l = m;
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> m : mat3x2_f32;
+
+fn conv_mat3x2_f32(val : mat3x2_f32) -> mat3x2<f32> {
+ return mat3x2<f32>(val.col0, val.col1, val.col2);
+}
+
+fn f() {
+ let l = conv_mat3x2_f32(m);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadColumn_ConstIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let l = a[1];
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn f() {
+ let l = a.col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadColumn_VariableIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn load_a_p0(p0 : u32) -> vec2<f32> {
+ switch(p0) {
+ case 0u: {
+ return a.col0;
+ }
+ case 1u: {
+ return a.col1;
+ }
+ case 2u: {
+ return a.col2;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadColumnSwizzle_ConstIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let l = a[1].yx;
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn f() {
+ let l = a.col1.yx;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadColumnSwizzle_VariableIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].yx;
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn load_a_p0_yx(p0 : u32) -> vec2<f32> {
+ switch(p0) {
+ case 0u: {
+ return a.col0.yx;
+ }
+ case 1u: {
+ return a.col1.yx;
+ }
+ case 2u: {
+ return a.col2.yx;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_yx(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let l = a[1][0];
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn f() {
+ let l = a.col1[0u];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let I = 0;
+ let l = a[I][0];
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn load_a_p0_0(p0 : u32) -> f32 {
+ switch(p0) {
+ case 0u: {
+ return a.col0[0u];
+ }
+ case 1u: {
+ return a.col1[0u];
+ }
+ case 2u: {
+ return a.col2[0u];
+ }
+ default: {
+ return f32();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_a_p0_0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let I = 0;
+ let l = a[1][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn f() {
+ let I = 0;
+ let l = a.col1[I];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, MatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex_Mat3x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
+
+fn f() {
+ let I = 0;
+ let l = a[I][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat3x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+ col2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : mat3x2_f32;
+
+fn load_a_p0_p1(p0 : u32, p1 : u32) -> f32 {
+ switch(p0) {
+ case 0u: {
+ return a.col0[p1];
+ }
+ case 1u: {
+ return a.col1[p1];
+ }
+ case 2u: {
+ return a.col2[p1];
+ }
+ default: {
+ return f32();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_a_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_NameCollision_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m_1 : i32,
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+)";
+
+ auto* expect = R"(
+struct S {
+ m_1 : i32,
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_1 : i32,
+ m__0 : vec2<f32>,
+ m__1 : vec2<f32>,
+ m__2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadStruct_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn f() {
+ let l = conv_S(s);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadMatrix_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.m;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m() -> mat3x2<f32> {
+ let s = &(s);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn f() {
+ let l = load_s_m();
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadColumn_ConstIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.m[1];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let l = s.m_1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadColumn_VariableIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[I];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0(p0 : u32) -> vec2<f32> {
+ switch(p0) {
+ case 0u: {
+ return s.m_0;
+ }
+ case 1u: {
+ return s.m_1;
+ }
+ case 2u: {
+ return s.m_2;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_s_m_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.m[1][0];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let l = s.m_1[0u];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[I][0];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0_0(p0 : u32) -> f32 {
+ switch(p0) {
+ case 0u: {
+ return s.m_0[0u];
+ }
+ case 1u: {
+ return s.m_1[0u];
+ }
+ case 2u: {
+ return s.m_2[0u];
+ }
+ default: {
+ return f32();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_s_m_p0_0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[1][I];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let I = 0;
+ let l = s.m_1[I];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 0;
+ let l = s.m[I][I];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_m_p0_p1(p0 : u32, p1 : u32) -> f32 {
+ switch(p0) {
+ case 0u: {
+ return s.m_0[p1];
+ }
+ case 1u: {
+ return s.m_1[p1];
+ }
+ case 2u: {
+ return s.m_2[p1];
+ }
+ default: {
+ return f32();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let l = load_s_m_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadArray_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn conv_arr3_S(val : array<S_std140, 3u>) -> array<S, 3u> {
+ var arr : array<S, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_S(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_S(a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadStruct_ConstIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a[2];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn f() {
+ let l = conv_S(a[2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadStruct_VariableIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_S(a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadMatrix_ConstArrayIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a[2].m;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_2_m() -> mat3x2<f32> {
+ let s = &(a[2u]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn f() {
+ let l = load_a_2_m();
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadMatrix_VariableArrayIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_p0_m(p0 : u32) -> mat3x2<f32> {
+ let s = &(a[p0]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_m(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayStructMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let l = a[2].m[1];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn f() {
+ let l = a[2u].m_1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayStructMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m[1];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m_1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayStructMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[2].m[I];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_2_m_p0(p0 : u32) -> vec2<f32> {
+ switch(p0) {
+ case 0u: {
+ return a[2u].m_0;
+ }
+ case 1u: {
+ return a[2u].m_1;
+ }
+ case 2u: {
+ return a[2u].m_2;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_2_m_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayStructMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].m[I];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
+
+fn load_a_p0_m_p1(p0 : u32, p1 : u32) -> vec2<f32> {
+ switch(p1) {
+ case 0u: {
+ return a[p0].m_0;
+ }
+ case 1u: {
+ return a[p0].m_1;
+ }
+ case 2u: {
+ return a[p0].m_2;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_m_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructArrayStructMatUniform_Loads_Mat3x2F32) {
+ auto* src = R"(
+struct Inner {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let l_a : array<Outer, 4> = a;
+ let l_a_1 : Outer = a[1];
+ let l_a_I : Outer = a[I];
+ let l_a_2_a : array<Inner, 4> = a[2].a;
+ let l_a_I_a : array<Inner, 4> = a[I].a;
+ let l_a_3_a_1 : Inner = a[3].a[1];
+ let l_a_3_a_I : Inner = a[3].a[I];
+ let l_a_I_a_1 : Inner = a[I].a[1];
+ let l_a_I_a_J : Inner = a[I].a[J];
+ let l_a_0_a_2_m : mat3x2<f32> = a[0].a[2].m;
+ let l_a_0_a_I_m : mat3x2<f32> = a[0].a[I].m;
+ let l_a_I_a_2_m : mat3x2<f32> = a[I].a[2].m;
+ let l_a_I_a_J_m : mat3x2<f32> = a[I].a[J].m;
+ let l_a_1_a_3_m_0 : vec2<f32> = a[1].a[3].m[0];
+ let l_a_I_a_J_m_K : vec2<f32> = a[I].a[J].m[K];
+ let l_a_2_a_0_m_1_0 : f32 = a[2].a[0].m[1][0];
+ let l_a_I_a_J_m_K_I : f32 = a[I].a[J].m[K][I];
+}
+)";
+
+ auto* expect = R"(
+struct Inner {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct Inner_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+struct Outer_std140 {
+ a : array<Inner_std140, 4u>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
+
+fn conv_Inner(val : Inner_std140) -> Inner {
+ return Inner(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
+ var arr : array<Inner, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Inner(val[i]);
+ }
+ return arr;
+}
+
+fn conv_Outer(val : Outer_std140) -> Outer {
+ return Outer(conv_arr4_Inner(val.a));
+}
+
+fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
+ var arr : array<Outer, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Outer(val[i]);
+ }
+ return arr;
+}
+
+fn load_a_0_a_2_m() -> mat3x2<f32> {
+ let s = &(a[0u].a[2u]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_0_a_p0_m(p0 : u32) -> mat3x2<f32> {
+ let s = &(a[0u].a[p0]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_p0_a_2_m(p0 : u32) -> mat3x2<f32> {
+ let s = &(a[p0].a[2u]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> mat3x2<f32> {
+ let s = &(a[p0].a[p1]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> vec2<f32> {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0;
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1;
+ }
+ case 2u: {
+ return a[p0].a[p1].m_2;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> f32 {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0[p3];
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1[p3];
+ }
+ case 2u: {
+ return a[p0].a[p1].m_2[p3];
+ }
+ default: {
+ return f32();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let l_a : array<Outer, 4> = conv_arr4_Outer(a);
+ let l_a_1 : Outer = conv_Outer(a[1u]);
+ let l_a_I : Outer = conv_Outer(a[I]);
+ let l_a_2_a : array<Inner, 4> = conv_arr4_Inner(a[2u].a);
+ let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
+ let l_a_3_a_1 : Inner = conv_Inner(a[3u].a[1u]);
+ let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
+ let l_a_I_a_1 : Inner = conv_Inner(a[I].a[1u]);
+ let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
+ let l_a_0_a_2_m : mat3x2<f32> = load_a_0_a_2_m();
+ let l_a_0_a_I_m : mat3x2<f32> = load_a_0_a_p0_m(u32(I));
+ let l_a_I_a_2_m : mat3x2<f32> = load_a_p0_a_2_m(u32(I));
+ let l_a_I_a_J_m : mat3x2<f32> = load_a_p0_a_p1_m(u32(I), u32(J));
+ let l_a_1_a_3_m_0 : vec2<f32> = a[1u].a[3u].m_0;
+ let l_a_I_a_J_m_K : vec2<f32> = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
+ let l_a_2_a_0_m_1_0 : f32 = a[2u].a[0u].m_1[0u];
+ let l_a_I_a_J_m_K_I : f32 = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructArrayStructMatUniform_LoadsViaPtrs_Mat3x2F32) {
+ auto* src = R"(
+struct Inner {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let p_a = &(a);
+ let p_a_3 = &((*(p_a))[3]);
+ let p_a_I = &((*(p_a))[I]);
+ let p_a_3_a = &((*(p_a_3)).a);
+ let p_a_I_a = &((*(p_a_I)).a);
+ let p_a_3_a_2 = &((*(p_a_3_a))[2]);
+ let p_a_3_a_I = &((*(p_a_3_a))[I]);
+ let p_a_I_a_2 = &((*(p_a_I_a))[2]);
+ let p_a_I_a_J = &((*(p_a_I_a))[J]);
+ let p_a_3_a_2_m = &((*(p_a_3_a_2)).m);
+ let p_a_3_a_I_m = &((*(p_a_3_a_I)).m);
+ let p_a_I_a_2_m = &((*(p_a_I_a_2)).m);
+ let p_a_I_a_J_m = &((*(p_a_I_a_J)).m);
+ let p_a_3_a_2_m_1 = &((*(p_a_3_a_2_m))[1]);
+ let p_a_I_a_J_m_K = &((*(p_a_I_a_J_m))[K]);
+ let l_a : array<Outer, 4> = *(p_a);
+ let l_a_3 : Outer = *(p_a_3);
+ let l_a_I : Outer = *(p_a_I);
+ let l_a_3_a : array<Inner, 4> = *(p_a_3_a);
+ let l_a_I_a : array<Inner, 4> = *(p_a_I_a);
+ let l_a_3_a_2 : Inner = *(p_a_3_a_2);
+ let l_a_3_a_I : Inner = *(p_a_3_a_I);
+ let l_a_I_a_2 : Inner = *(p_a_I_a_2);
+ let l_a_I_a_J : Inner = *(p_a_I_a_J);
+ let l_a_3_a_2_m : mat3x2<f32> = *(p_a_3_a_2_m);
+ let l_a_3_a_I_m : mat3x2<f32> = *(p_a_3_a_I_m);
+ let l_a_I_a_2_m : mat3x2<f32> = *(p_a_I_a_2_m);
+ let l_a_I_a_J_m : mat3x2<f32> = *(p_a_I_a_J_m);
+ let l_a_3_a_2_m_1 : vec2<f32> = *(p_a_3_a_2_m_1);
+ let l_a_I_a_J_m_K : vec2<f32> = *(p_a_I_a_J_m_K);
+ let l_a_2_a_0_m_1_0 : f32 = (*(p_a_3_a_2_m_1))[0];
+ let l_a_I_a_J_m_K_I : f32 = (*(p_a_I_a_J_m_K))[I];
+}
+)";
+
+ auto* expect = R"(
+struct Inner {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct Inner_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+struct Outer {
+ a : array<Inner, 4>,
+}
+
+struct Outer_std140 {
+ a : array<Inner_std140, 4u>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
+
+fn conv_Inner(val : Inner_std140) -> Inner {
+ return Inner(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
+ var arr : array<Inner, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Inner(val[i]);
+ }
+ return arr;
+}
+
+fn conv_Outer(val : Outer_std140) -> Outer {
+ return Outer(conv_arr4_Inner(val.a));
+}
+
+fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
+ var arr : array<Outer, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_Outer(val[i]);
+ }
+ return arr;
+}
+
+fn load_a_3_a_2_m() -> mat3x2<f32> {
+ let s = &(a[3u].a[2u]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_3_a_p0_m(p0 : u32) -> mat3x2<f32> {
+ let s = &(a[3u].a[p0]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_p0_a_2_m(p0 : u32) -> mat3x2<f32> {
+ let s = &(a[p0].a[2u]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> mat3x2<f32> {
+ let s = &(a[p0].a[p1]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> vec2<f32> {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0;
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1;
+ }
+ case 2u: {
+ return a[p0].a[p1].m_2;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> f32 {
+ switch(p2) {
+ case 0u: {
+ return a[p0].a[p1].m_0[p3];
+ }
+ case 1u: {
+ return a[p0].a[p1].m_1[p3];
+ }
+ case 2u: {
+ return a[p0].a[p1].m_2[p3];
+ }
+ default: {
+ return f32();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let K = 0;
+ let p_a = conv_arr4_Outer(a);
+ let p_a_3 = conv_Outer(a[3u]);
+ let p_a_I = conv_Outer(a[I]);
+ let p_a_3_a = conv_arr4_Inner(a[3u].a);
+ let p_a_I_a = conv_arr4_Inner(a[I].a);
+ let p_a_3_a_2 = conv_Inner(a[3u].a[2u]);
+ let p_a_3_a_I = conv_Inner(a[3u].a[I]);
+ let p_a_I_a_2 = conv_Inner(a[I].a[2u]);
+ let p_a_I_a_J = conv_Inner(a[I].a[J]);
+ let p_a_3_a_2_m = load_a_3_a_2_m();
+ let p_a_3_a_I_m = load_a_3_a_p0_m(u32(I));
+ let p_a_I_a_2_m = load_a_p0_a_2_m(u32(I));
+ let p_a_I_a_J_m = load_a_p0_a_p1_m(u32(I), u32(J));
+ let p_a_3_a_2_m_1 = a[3u].a[2u].m_1;
+ let p_a_I_a_J_m_K = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
+ let l_a : array<Outer, 4> = conv_arr4_Outer(a);
+ let l_a_3 : Outer = conv_Outer(a[3u]);
+ let l_a_I : Outer = conv_Outer(a[I]);
+ let l_a_3_a : array<Inner, 4> = conv_arr4_Inner(a[3u].a);
+ let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
+ let l_a_3_a_2 : Inner = conv_Inner(a[3u].a[2u]);
+ let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
+ let l_a_I_a_2 : Inner = conv_Inner(a[I].a[2u]);
+ let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
+ let l_a_3_a_2_m : mat3x2<f32> = load_a_3_a_2_m();
+ let l_a_3_a_I_m : mat3x2<f32> = load_a_3_a_p0_m(u32(I));
+ let l_a_I_a_2_m : mat3x2<f32> = load_a_p0_a_2_m(u32(I));
+ let l_a_I_a_J_m : mat3x2<f32> = load_a_p0_a_p1_m(u32(I), u32(J));
+ let l_a_3_a_2_m_1 : vec2<f32> = a[3u].a[2u].m_1;
+ let l_a_I_a_J_m_K : vec2<f32> = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
+ let l_a_2_a_0_m_1_0 : f32 = a[3u].a[2u].m_1[0u];
+ let l_a_I_a_J_m_K_I : f32 = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyArray_UniformToStorage_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 4>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn f() {
+ s = u;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn conv_arr4_S(val : array<S_std140, 4u>) -> array<S, 4u> {
+ var arr : array<S, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_S(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ s = conv_arr4_S(u);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyStruct_UniformToWorkgroup_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 4>;
+
+var<workgroup> w : array<S, 4>;
+
+fn f() {
+ w[0] = u[1];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ v : vec4<i32>,
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
+
+var<workgroup> w : array<S, 4>;
+
+fn conv_S(val : S_std140) -> S {
+ return S(val.v, mat3x2<f32>(val.m_0, val.m_1, val.m_2));
+}
+
+fn f() {
+ w[0] = conv_S(u[1u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyMatrix_UniformToPrivate_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 3>;
+
+var<private> p : array<S, 4>;
+
+fn f() {
+ p[2].m = u[1].m;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ v : vec4<i32>,
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
+
+var<private> p : array<S, 4>;
+
+fn load_u_1_m() -> mat3x2<f32> {
+ let s = &(u[1u]);
+ return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
+}
+
+fn f() {
+ p[2].m = load_u_1_m();
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyColumn_UniformToStorage_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 3>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn f() {
+ s[3].m[1] = u[2].m[0];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
+
+@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
+
+fn f() {
+ s[3].m[1] = u[2u].m_0;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyColumnSwizzle_UniformToWorkgroup_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 4>;
+
+var<workgroup> w : array<S, 4>;
+
+fn f() {
+ w[3].m[1] = u[2].m[0].yx.yx;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
+
+var<workgroup> w : array<S, 4>;
+
+fn f() {
+ w[3].m[1] = u[2u].m_0.yx.yx;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyScalar_UniformToPrivate_Mat3x2F32) {
+ auto* src = R"(
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S, 3>;
+
+var<private> p : array<S, 4>;
+
+fn f() {
+ p[3].m[1].x = u[2].m[0].y;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ v : vec4<i32>,
+ @size(64)
+ m : mat3x2<f32>,
+}
+
+struct S_std140 {
+ v : vec4<i32>,
+ m_0 : vec2<f32>,
+ m_1 : vec2<f32>,
+ @size(48)
+ m_2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
+
+var<private> p : array<S, 4>;
+
+fn f() {
+ p[3].m[1].x = u[2u].m_0[1u];
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayMatUniform_LoadArray_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
+
+fn f() {
+ let l = a;
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
+ var arr : array<mat2x2<f32>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x2_f32(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_mat2x2_f32(a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayMatUniform_LoadMatrix_ConstArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
+
+fn f() {
+ let l = a[2];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let l = conv_mat2x2_f32(a[2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayMatUniform_LoadMatrix_VariableArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x2_f32(a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
+
+fn f() {
+ let l = a[2][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
+
+fn f() {
+ let l = a[2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
+
+fn f() {
+ let I = 1;
+ let l = a[I].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[2][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
+
+fn load_a_2_p0(p0 : u32) -> vec2<f32> {
+ switch(p0) {
+ case 0u: {
+ return a[2u].col0;
+ }
+ case 1u: {
+ return a[2u].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_2_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
+
+fn load_a_p0_p1(p0 : u32, p1 : u32) -> vec2<f32> {
+ switch(p1) {
+ case 0u: {
+ return a[p0].col0;
+ }
+ case 1u: {
+ return a[p0].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructArrayMatUniform_LoadStruct_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s;
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
+ var arr : array<mat2x2<f32>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x2_f32(val[i]);
+ }
+ return arr;
+}
+
+fn conv_S(val : S_std140) -> S {
+ return S(conv_arr3_mat2x2_f32(val.a));
+}
+
+fn f() {
+ let l = conv_S(s);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructArrayMatUniform_LoadArray_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.a;
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
+ var arr : array<mat2x2<f32>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x2_f32(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_mat2x2_f32(s.a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructArrayMatUniform_LoadMatrix_ConstArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.a[2];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let l = conv_mat2x2_f32(s.a[2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, StructArrayMatUniform_LoadMatrix_VariableArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x2_f32(s.a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ StructArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let l = s.a[2][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let l = s.a[2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ StructArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ StructArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[2][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_a_2_p0(p0 : u32) -> vec2<f32> {
+ switch(p0) {
+ case 0u: {
+ return s.a[2u].col0;
+ }
+ case 1u: {
+ return s.a[2u].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_s_a_2_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ StructArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+@group(0) @binding(0) var<uniform> s : S;
+
+fn f() {
+ let I = 1;
+ let l = s.a[I][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+struct S {
+ a : array<mat2x2<f32>, 3>,
+}
+
+struct S_std140 {
+ a : array<mat2x2_f32, 3u>,
+}
+
+@group(0) @binding(0) var<uniform> s : S_std140;
+
+fn load_s_a_p0_p1(p0 : u32, p1 : u32) -> vec2<f32> {
+ switch(p1) {
+ case 0u: {
+ return s.a[p0].col0;
+ }
+ case 1u: {
+ return s.a[p0].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_s_a_p0_p1(u32(I), u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayArrayMatUniform_LoadArrays_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let l = a;
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
+ var arr : array<mat2x2<f32>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x2_f32(val[i]);
+ }
+ return arr;
+}
+
+fn conv_arr4_arr3_mat2x2_f32(val : array<array<mat2x2_f32, 3u>, 4u>) -> array<array<mat2x2<f32>, 3u>, 4u> {
+ var arr : array<array<mat2x2<f32>, 3u>, 4u>;
+ for(var i : u32; (i < 4u); i = (i + 1)) {
+ arr[i] = conv_arr3_mat2x2_f32(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr4_arr3_mat2x2_f32(a);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayArrayMatUniform_LoadArray_ConstOuterArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let l = a[3];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
+ var arr : array<mat2x2<f32>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x2_f32(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let l = conv_arr3_mat2x2_f32(a[3u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32, ArrayArrayMatUniform_LoadArray_VariableOuterArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
+ var arr : array<mat2x2<f32>, 3u>;
+ for(var i : u32; (i < 3u); i = (i + 1)) {
+ arr[i] = conv_mat2x2_f32(val[i]);
+ }
+ return arr;
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_arr3_mat2x2_f32(a[I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_ConstInnerArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let l = a[3][2];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let l = conv_mat2x2_f32(a[3u][2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_VariableInnerArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[3][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x2_f32(a[3u][I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_ConstInnerArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][2];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x2_f32(a[I][2u]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(Std140Test_F32,
+ ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_VariableInnerArrayIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
+ return mat2x2<f32>(val.col0, val.col1);
+}
+
+fn f() {
+ let I = 1;
+ let l = conv_mat2x2_f32(a[I][I]);
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let l = a[3][2][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn f() {
+ let l = a[3u][2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[3][2][I];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn load_a_3_2_p0(p0 : u32) -> vec2<f32> {
+ switch(p0) {
+ case 0u: {
+ return a[3u][2u].col0;
+ }
+ case 1u: {
+ return a[3u][2u].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let l = load_a_3_2_p0(u32(I));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[3][I][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn f() {
+ let I = 1;
+ let l = a[3u][I].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[3][I][J];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn load_a_3_p0_p1(p0 : u32, p1 : u32) -> vec2<f32> {
+ switch(p1) {
+ case 0u: {
+ return a[3u][p0].col0;
+ }
+ case 1u: {
+ return a[3u][p0].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = load_a_3_p0_p1(u32(I), u32(J));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][2][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn f() {
+ let I = 1;
+ let l = a[I][2u].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[I][2][J];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn load_a_p0_2_p1(p0 : u32, p1 : u32) -> vec2<f32> {
+ switch(p1) {
+ case 0u: {
+ return a[p0][2u].col0;
+ }
+ case 1u: {
+ return a[p0][2u].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = load_a_p0_2_p1(u32(I), u32(J));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[I][J][1];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn f() {
+ let I = 1;
+ let J = 2;
+ let l = a[I][J].col1;
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(
+ Std140Test_F32,
+ ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
+
+fn f() {
+ let I = 0;
+ let J = 1;
+ let K = 2;
+ let l = a[I][J][K];
+}
+)";
+
+ auto* expect = R"(
+struct mat2x2_f32 {
+ col0 : vec2<f32>,
+ col1 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
+
+fn load_a_p0_p1_p2(p0 : u32, p1 : u32, p2 : u32) -> vec2<f32> {
+ switch(p2) {
+ case 0u: {
+ return a[p0][p1].col0;
+ }
+ case 1u: {
+ return a[p0][p1].col1;
+ }
+ default: {
+ return vec2<f32>();
+ }
+ }
+}
+
+fn f() {
+ let I = 0;
+ let J = 1;
+ let K = 2;
+ let l = load_a_p0_p1_p2(u32(I), u32(J), u32(K));
+}
+)";
+
+ auto got = Run<Std140>(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+} // namespace
+} // namespace tint::transform
diff --git a/src/tint/transform/std140_test.cc b/src/tint/transform/std140_test.cc
index 1ec2e09..73221bc 100644
--- a/src/tint/transform/std140_test.cc
+++ b/src/tint/transform/std140_test.cc
@@ -21,6 +21,12 @@
#include "src/tint/transform/test_helper.h"
#include "src/tint/utils/string.h"
+// This file contains the should-run tests and a trival empty module test for Std140 transform.
+// For testing transform results with clear readability, please refer to std140_f32_test.cc for f32
+// matricies and std140_f16_test.cc for f16 matricies. For exhaustive tests that run Std140
+// transform on all shape of both f32 and f16 matricies and loop on all valid literal index when
+// required, please refer to std140_exhaustive_test.cc.
+
namespace tint::transform {
namespace {
@@ -96,6 +102,8 @@
TEST_P(Std140TestShouldRun, StructStorage) {
std::string src = R"(
+enable f16;
+
struct S {
m : ${mat},
}
@@ -110,6 +118,8 @@
TEST_P(Std140TestShouldRun, StructUniform) {
std::string src = R"(
+enable f16;
+
struct S {
m : ${mat},
}
@@ -124,6 +134,8 @@
TEST_P(Std140TestShouldRun, ArrayStorage) {
std::string src = R"(
+enable f16;
+
@group(0) @binding(0) var<storage> s : array<${mat}, 2>;
)";
@@ -141,6 +153,8 @@
}
std::string src = R"(
+enable f16;
+
@group(0) @binding(0) var<uniform> s : array<${mat}, 2>;
)";
@@ -161,6 +175,15 @@
{4, 2, MatrixType::f32},
{4, 3, MatrixType::f32},
{4, 4, MatrixType::f32},
+ {2, 2, MatrixType::f16},
+ {2, 3, MatrixType::f16},
+ {2, 4, MatrixType::f16},
+ {3, 2, MatrixType::f16},
+ {3, 3, MatrixType::f16},
+ {3, 4, MatrixType::f16},
+ {4, 2, MatrixType::f16},
+ {4, 3, MatrixType::f16},
+ {4, 4, MatrixType::f16},
}));
TEST_F(Std140Test, EmptyModule) {
@@ -173,3336 +196,5 @@
EXPECT_EQ(expect, str(got));
}
-using Std140Test_F32 = Std140Test;
-
-TEST_F(Std140Test_F32, StructMatricesUniform) {
- auto* src = R"(
-struct S2x2F32 {
- m : mat2x2<f32>,
-}
-struct S3x2F32 {
- m : mat3x2<f32>,
-}
-struct S4x2F32 {
- m : mat4x2<f32>,
-}
-struct S2x3F32 {
- m : mat2x3<f32>,
-}
-struct S3x3F32 {
- m : mat3x3<f32>,
-}
-struct S4x3F32 {
- m : mat4x3<f32>,
-}
-struct S2x4F32 {
- m : mat2x4<f32>,
-}
-struct S3x4F32 {
- m : mat3x4<f32>,
-}
-struct S4x4F32 {
- m : mat4x4<f32>,
-}
-
-@group(2) @binding(2) var<uniform> s2x2f32 : S2x2F32;
-@group(3) @binding(2) var<uniform> s3x2f32 : S3x2F32;
-@group(4) @binding(2) var<uniform> s4x2f32 : S4x2F32;
-@group(2) @binding(3) var<uniform> s2x3f32 : S2x3F32;
-@group(3) @binding(3) var<uniform> s3x3f32 : S3x3F32;
-@group(4) @binding(3) var<uniform> s4x3f32 : S4x3F32;
-@group(2) @binding(4) var<uniform> s2x4f32 : S2x4F32;
-@group(3) @binding(4) var<uniform> s3x4f32 : S3x4F32;
-@group(4) @binding(4) var<uniform> s4x4f32 : S4x4F32;
-)";
-
- auto* expect = R"(
-struct S2x2F32 {
- m : mat2x2<f32>,
-}
-
-struct S2x2F32_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
-}
-
-struct S3x2F32 {
- m : mat3x2<f32>,
-}
-
-struct S3x2F32_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-struct S4x2F32 {
- m : mat4x2<f32>,
-}
-
-struct S4x2F32_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
- m_3 : vec2<f32>,
-}
-
-struct S2x3F32 {
- m : mat2x3<f32>,
-}
-
-struct S3x3F32 {
- m : mat3x3<f32>,
-}
-
-struct S4x3F32 {
- m : mat4x3<f32>,
-}
-
-struct S2x4F32 {
- m : mat2x4<f32>,
-}
-
-struct S3x4F32 {
- m : mat3x4<f32>,
-}
-
-struct S4x4F32 {
- m : mat4x4<f32>,
-}
-
-@group(2) @binding(2) var<uniform> s2x2f32 : S2x2F32_std140;
-
-@group(3) @binding(2) var<uniform> s3x2f32 : S3x2F32_std140;
-
-@group(4) @binding(2) var<uniform> s4x2f32 : S4x2F32_std140;
-
-@group(2) @binding(3) var<uniform> s2x3f32 : S2x3F32;
-
-@group(3) @binding(3) var<uniform> s3x3f32 : S3x3F32;
-
-@group(4) @binding(3) var<uniform> s4x3f32 : S4x3F32;
-
-@group(2) @binding(4) var<uniform> s2x4f32 : S2x4F32;
-
-@group(3) @binding(4) var<uniform> s3x4f32 : S3x4F32;
-
-@group(4) @binding(4) var<uniform> s4x4f32 : S4x4F32;
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-// In the following tests we only test `mat2x2<f32>` for matrix used as array element type and
-// `mat3x2<f32>` otherwise, and set all constant column index to 1, row index 0, inner array index
-// 2, and outer array index 3. For exhaustive tests, i.e. tests on all matrix shape and different
-// valid constant index, please refer to std140_exhaustive_test.cc
-
-TEST_F(Std140Test_F32, SingleStructMatUniform_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, CustomAlign_Mat3x2F32) {
- auto* src = R"(
-struct S {
- before : i32,
- @align(128)
- m : mat3x2<f32>,
- after : i32,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-)";
-
- auto* expect = R"(
-struct S {
- before : i32,
- @align(128)
- m : mat3x2<f32>,
- after : i32,
-}
-
-struct S_std140 {
- before : i32,
- @align(128i)
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
- after : i32,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, CustomSizeMat_Mat3x2F32) {
- auto* src = R"(
-struct S {
- before : i32,
- @size(128)
- m : mat3x2<f32>,
- after : i32,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-)";
-
- auto* expect = R"(
-struct S {
- before : i32,
- @size(128)
- m : mat3x2<f32>,
- after : i32,
-}
-
-struct S_std140 {
- before : i32,
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(112)
- m_2 : vec2<f32>,
- after : i32,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, CustomAlignAndSize_Mat3x2F32) {
- auto* src = R"(
-struct S {
- before : i32,
- @align(128) @size(128)
- m : mat3x2<f32>,
- after : i32,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-)";
-
- auto* expect = R"(
-struct S {
- before : i32,
- @align(128) @size(128)
- m : mat3x2<f32>,
- after : i32,
-}
-
-struct S_std140 {
- before : i32,
- @align(128i)
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(112)
- m_2 : vec2<f32>,
- after : i32,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatrixUsageInForLoop_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- for(var i = u32(s.m[0][0]); (i < u32(s.m[i][1])); i += u32(s.m[1][i])) {
- }
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn load_s_m_p0_1(p0 : u32) -> f32 {
- switch(p0) {
- case 0u: {
- return s.m_0[1u];
- }
- case 1u: {
- return s.m_1[1u];
- }
- case 2u: {
- return s.m_2[1u];
- }
- default: {
- return f32();
- }
- }
-}
-
-fn f() {
- for(var i = u32(s.m_0[0u]); (i < u32(load_s_m_p0_1(u32(i)))); i += u32(s.m_1[i])) {
- }
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadMatrix_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> m : mat3x2<f32>;
-
-fn f() {
- let l = m;
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> m : mat3x2_f32;
-
-fn conv_mat3x2_f32(val : mat3x2_f32) -> mat3x2<f32> {
- return mat3x2<f32>(val.col0, val.col1, val.col2);
-}
-
-fn f() {
- let l = conv_mat3x2_f32(m);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadColumn_ConstIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let l = a[1];
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn f() {
- let l = a.col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadColumn_VariableIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let I = 1;
- let l = a[I];
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn load_a_p0(p0 : u32) -> vec2<f32> {
- switch(p0) {
- case 0u: {
- return a.col0;
- }
- case 1u: {
- return a.col1;
- }
- case 2u: {
- return a.col2;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_a_p0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadColumnSwizzle_ConstIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let l = a[1].yx;
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn f() {
- let l = a.col1.yx;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadColumnSwizzle_VariableIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let I = 1;
- let l = a[I].yx;
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn load_a_p0_yx(p0 : u32) -> vec2<f32> {
- switch(p0) {
- case 0u: {
- return a.col0.yx;
- }
- case 1u: {
- return a.col1.yx;
- }
- case 2u: {
- return a.col2.yx;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_a_p0_yx(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let l = a[1][0];
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn f() {
- let l = a.col1[0u];
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let I = 0;
- let l = a[I][0];
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn load_a_p0_0(p0 : u32) -> f32 {
- switch(p0) {
- case 0u: {
- return a.col0[0u];
- }
- case 1u: {
- return a.col1[0u];
- }
- case 2u: {
- return a.col2[0u];
- }
- default: {
- return f32();
- }
- }
-}
-
-fn f() {
- let I = 0;
- let l = load_a_p0_0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let I = 0;
- let l = a[1][I];
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn f() {
- let I = 0;
- let l = a.col1[I];
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, MatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex_Mat3x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : mat3x2<f32>;
-
-fn f() {
- let I = 0;
- let l = a[I][I];
-}
-)";
-
- auto* expect = R"(
-struct mat3x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
- col2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : mat3x2_f32;
-
-fn load_a_p0_p1(p0 : u32, p1 : u32) -> f32 {
- switch(p0) {
- case 0u: {
- return a.col0[p1];
- }
- case 1u: {
- return a.col1[p1];
- }
- case 2u: {
- return a.col2[p1];
- }
- default: {
- return f32();
- }
- }
-}
-
-fn f() {
- let I = 0;
- let l = load_a_p0_p1(u32(I), u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_NameCollision_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m_1 : i32,
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-)";
-
- auto* expect = R"(
-struct S {
- m_1 : i32,
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_1 : i32,
- m__0 : vec2<f32>,
- m__1 : vec2<f32>,
- m__2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadStruct_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s;
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn conv_S(val : S_std140) -> S {
- return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn f() {
- let l = conv_S(s);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadMatrix_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s.m;
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn load_s_m() -> mat3x2<f32> {
- let s = &(s);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn f() {
- let l = load_s_m();
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadColumn_ConstIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s.m[1];
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn f() {
- let l = s.m_1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadColumn_VariableIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 0;
- let l = s.m[I];
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn load_s_m_p0(p0 : u32) -> vec2<f32> {
- switch(p0) {
- case 0u: {
- return s.m_0;
- }
- case 1u: {
- return s.m_1;
- }
- case 2u: {
- return s.m_2;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 0;
- let l = load_s_m_p0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s.m[1][0];
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn f() {
- let l = s.m_1[0u];
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 0;
- let l = s.m[I][0];
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn load_s_m_p0_0(p0 : u32) -> f32 {
- switch(p0) {
- case 0u: {
- return s.m_0[0u];
- }
- case 1u: {
- return s.m_1[0u];
- }
- case 2u: {
- return s.m_2[0u];
- }
- default: {
- return f32();
- }
- }
-}
-
-fn f() {
- let I = 0;
- let l = load_s_m_p0_0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 0;
- let l = s.m[1][I];
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn f() {
- let I = 0;
- let l = s.m_1[I];
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructMatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 0;
- let l = s.m[I][I];
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn load_s_m_p0_p1(p0 : u32, p1 : u32) -> f32 {
- switch(p0) {
- case 0u: {
- return s.m_0[p1];
- }
- case 1u: {
- return s.m_1[p1];
- }
- case 2u: {
- return s.m_2[p1];
- }
- default: {
- return f32();
- }
- }
-}
-
-fn f() {
- let I = 0;
- let l = load_s_m_p0_p1(u32(I), u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadArray_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let l = a;
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn conv_S(val : S_std140) -> S {
- return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn conv_arr3_S(val : array<S_std140, 3u>) -> array<S, 3u> {
- var arr : array<S, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- arr[i] = conv_S(val[i]);
- }
- return arr;
-}
-
-fn f() {
- let l = conv_arr3_S(a);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadStruct_ConstIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let l = a[2];
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn conv_S(val : S_std140) -> S {
- return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn f() {
- let l = conv_S(a[2u]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadStruct_VariableIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let I = 1;
- let l = a[I];
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn conv_S(val : S_std140) -> S {
- return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn f() {
- let I = 1;
- let l = conv_S(a[I]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadMatrix_ConstArrayIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let l = a[2].m;
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn load_a_2_m() -> mat3x2<f32> {
- let s = &(a[2u]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn f() {
- let l = load_a_2_m();
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_LoadMatrix_VariableArrayIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let I = 1;
- let l = a[I].m;
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn load_a_p0_m(p0 : u32) -> mat3x2<f32> {
- let s = &(a[p0]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn f() {
- let I = 1;
- let l = load_a_p0_m(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayStructMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let l = a[2].m[1];
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn f() {
- let l = a[2u].m_1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayStructMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let I = 1;
- let l = a[I].m[1];
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn f() {
- let I = 1;
- let l = a[I].m_1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayStructMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let I = 1;
- let l = a[2].m[I];
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn load_a_2_m_p0(p0 : u32) -> vec2<f32> {
- switch(p0) {
- case 0u: {
- return a[2u].m_0;
- }
- case 1u: {
- return a[2u].m_1;
- }
- case 2u: {
- return a[2u].m_2;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_a_2_m_p0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayStructMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S, 3>;
-
-fn f() {
- let I = 1;
- let l = a[I].m[I];
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
-
-fn load_a_p0_m_p1(p0 : u32, p1 : u32) -> vec2<f32> {
- switch(p1) {
- case 0u: {
- return a[p0].m_0;
- }
- case 1u: {
- return a[p0].m_1;
- }
- case 2u: {
- return a[p0].m_2;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_a_p0_m_p1(u32(I), u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructArrayStructMatUniform_Loads_Mat3x2F32) {
- auto* src = R"(
-struct Inner {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct Outer {
- a : array<Inner, 4>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
-
-fn f() {
- let I = 1;
- let J = 2;
- let K = 0;
- let l_a : array<Outer, 4> = a;
- let l_a_1 : Outer = a[1];
- let l_a_I : Outer = a[I];
- let l_a_2_a : array<Inner, 4> = a[2].a;
- let l_a_I_a : array<Inner, 4> = a[I].a;
- let l_a_3_a_1 : Inner = a[3].a[1];
- let l_a_3_a_I : Inner = a[3].a[I];
- let l_a_I_a_1 : Inner = a[I].a[1];
- let l_a_I_a_J : Inner = a[I].a[J];
- let l_a_0_a_2_m : mat3x2<f32> = a[0].a[2].m;
- let l_a_0_a_I_m : mat3x2<f32> = a[0].a[I].m;
- let l_a_I_a_2_m : mat3x2<f32> = a[I].a[2].m;
- let l_a_I_a_J_m : mat3x2<f32> = a[I].a[J].m;
- let l_a_1_a_3_m_0 : vec2<f32> = a[1].a[3].m[0];
- let l_a_I_a_J_m_K : vec2<f32> = a[I].a[J].m[K];
- let l_a_2_a_0_m_1_0 : f32 = a[2].a[0].m[1][0];
- let l_a_I_a_J_m_K_I : f32 = a[I].a[J].m[K][I];
-}
-)";
-
- auto* expect = R"(
-struct Inner {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct Inner_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-struct Outer {
- a : array<Inner, 4>,
-}
-
-struct Outer_std140 {
- a : array<Inner_std140, 4u>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
-
-fn conv_Inner(val : Inner_std140) -> Inner {
- return Inner(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
- var arr : array<Inner, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- arr[i] = conv_Inner(val[i]);
- }
- return arr;
-}
-
-fn conv_Outer(val : Outer_std140) -> Outer {
- return Outer(conv_arr4_Inner(val.a));
-}
-
-fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
- var arr : array<Outer, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- arr[i] = conv_Outer(val[i]);
- }
- return arr;
-}
-
-fn load_a_0_a_2_m() -> mat3x2<f32> {
- let s = &(a[0u].a[2u]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_0_a_p0_m(p0 : u32) -> mat3x2<f32> {
- let s = &(a[0u].a[p0]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_p0_a_2_m(p0 : u32) -> mat3x2<f32> {
- let s = &(a[p0].a[2u]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> mat3x2<f32> {
- let s = &(a[p0].a[p1]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> vec2<f32> {
- switch(p2) {
- case 0u: {
- return a[p0].a[p1].m_0;
- }
- case 1u: {
- return a[p0].a[p1].m_1;
- }
- case 2u: {
- return a[p0].a[p1].m_2;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> f32 {
- switch(p2) {
- case 0u: {
- return a[p0].a[p1].m_0[p3];
- }
- case 1u: {
- return a[p0].a[p1].m_1[p3];
- }
- case 2u: {
- return a[p0].a[p1].m_2[p3];
- }
- default: {
- return f32();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let J = 2;
- let K = 0;
- let l_a : array<Outer, 4> = conv_arr4_Outer(a);
- let l_a_1 : Outer = conv_Outer(a[1u]);
- let l_a_I : Outer = conv_Outer(a[I]);
- let l_a_2_a : array<Inner, 4> = conv_arr4_Inner(a[2u].a);
- let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
- let l_a_3_a_1 : Inner = conv_Inner(a[3u].a[1u]);
- let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
- let l_a_I_a_1 : Inner = conv_Inner(a[I].a[1u]);
- let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
- let l_a_0_a_2_m : mat3x2<f32> = load_a_0_a_2_m();
- let l_a_0_a_I_m : mat3x2<f32> = load_a_0_a_p0_m(u32(I));
- let l_a_I_a_2_m : mat3x2<f32> = load_a_p0_a_2_m(u32(I));
- let l_a_I_a_J_m : mat3x2<f32> = load_a_p0_a_p1_m(u32(I), u32(J));
- let l_a_1_a_3_m_0 : vec2<f32> = a[1u].a[3u].m_0;
- let l_a_I_a_J_m_K : vec2<f32> = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
- let l_a_2_a_0_m_1_0 : f32 = a[2u].a[0u].m_1[0u];
- let l_a_I_a_J_m_K_I : f32 = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructArrayStructMatUniform_LoadsViaPtrs_Mat3x2F32) {
- auto* src = R"(
-struct Inner {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct Outer {
- a : array<Inner, 4>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
-
-fn f() {
- let I = 1;
- let J = 2;
- let K = 0;
- let p_a = &(a);
- let p_a_3 = &((*(p_a))[3]);
- let p_a_I = &((*(p_a))[I]);
- let p_a_3_a = &((*(p_a_3)).a);
- let p_a_I_a = &((*(p_a_I)).a);
- let p_a_3_a_2 = &((*(p_a_3_a))[2]);
- let p_a_3_a_I = &((*(p_a_3_a))[I]);
- let p_a_I_a_2 = &((*(p_a_I_a))[2]);
- let p_a_I_a_J = &((*(p_a_I_a))[J]);
- let p_a_3_a_2_m = &((*(p_a_3_a_2)).m);
- let p_a_3_a_I_m = &((*(p_a_3_a_I)).m);
- let p_a_I_a_2_m = &((*(p_a_I_a_2)).m);
- let p_a_I_a_J_m = &((*(p_a_I_a_J)).m);
- let p_a_3_a_2_m_1 = &((*(p_a_3_a_2_m))[1]);
- let p_a_I_a_J_m_K = &((*(p_a_I_a_J_m))[K]);
- let l_a : array<Outer, 4> = *(p_a);
- let l_a_3 : Outer = *(p_a_3);
- let l_a_I : Outer = *(p_a_I);
- let l_a_3_a : array<Inner, 4> = *(p_a_3_a);
- let l_a_I_a : array<Inner, 4> = *(p_a_I_a);
- let l_a_3_a_2 : Inner = *(p_a_3_a_2);
- let l_a_3_a_I : Inner = *(p_a_3_a_I);
- let l_a_I_a_2 : Inner = *(p_a_I_a_2);
- let l_a_I_a_J : Inner = *(p_a_I_a_J);
- let l_a_3_a_2_m : mat3x2<f32> = *(p_a_3_a_2_m);
- let l_a_3_a_I_m : mat3x2<f32> = *(p_a_3_a_I_m);
- let l_a_I_a_2_m : mat3x2<f32> = *(p_a_I_a_2_m);
- let l_a_I_a_J_m : mat3x2<f32> = *(p_a_I_a_J_m);
- let l_a_3_a_2_m_1 : vec2<f32> = *(p_a_3_a_2_m_1);
- let l_a_I_a_J_m_K : vec2<f32> = *(p_a_I_a_J_m_K);
- let l_a_2_a_0_m_1_0 : f32 = (*(p_a_3_a_2_m_1))[0];
- let l_a_I_a_J_m_K_I : f32 = (*(p_a_I_a_J_m_K))[I];
-}
-)";
-
- auto* expect = R"(
-struct Inner {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct Inner_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-struct Outer {
- a : array<Inner, 4>,
-}
-
-struct Outer_std140 {
- a : array<Inner_std140, 4u>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
-
-fn conv_Inner(val : Inner_std140) -> Inner {
- return Inner(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
- var arr : array<Inner, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- arr[i] = conv_Inner(val[i]);
- }
- return arr;
-}
-
-fn conv_Outer(val : Outer_std140) -> Outer {
- return Outer(conv_arr4_Inner(val.a));
-}
-
-fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
- var arr : array<Outer, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- arr[i] = conv_Outer(val[i]);
- }
- return arr;
-}
-
-fn load_a_3_a_2_m() -> mat3x2<f32> {
- let s = &(a[3u].a[2u]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_3_a_p0_m(p0 : u32) -> mat3x2<f32> {
- let s = &(a[3u].a[p0]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_p0_a_2_m(p0 : u32) -> mat3x2<f32> {
- let s = &(a[p0].a[2u]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> mat3x2<f32> {
- let s = &(a[p0].a[p1]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> vec2<f32> {
- switch(p2) {
- case 0u: {
- return a[p0].a[p1].m_0;
- }
- case 1u: {
- return a[p0].a[p1].m_1;
- }
- case 2u: {
- return a[p0].a[p1].m_2;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> f32 {
- switch(p2) {
- case 0u: {
- return a[p0].a[p1].m_0[p3];
- }
- case 1u: {
- return a[p0].a[p1].m_1[p3];
- }
- case 2u: {
- return a[p0].a[p1].m_2[p3];
- }
- default: {
- return f32();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let J = 2;
- let K = 0;
- let p_a = conv_arr4_Outer(a);
- let p_a_3 = conv_Outer(a[3u]);
- let p_a_I = conv_Outer(a[I]);
- let p_a_3_a = conv_arr4_Inner(a[3u].a);
- let p_a_I_a = conv_arr4_Inner(a[I].a);
- let p_a_3_a_2 = conv_Inner(a[3u].a[2u]);
- let p_a_3_a_I = conv_Inner(a[3u].a[I]);
- let p_a_I_a_2 = conv_Inner(a[I].a[2u]);
- let p_a_I_a_J = conv_Inner(a[I].a[J]);
- let p_a_3_a_2_m = load_a_3_a_2_m();
- let p_a_3_a_I_m = load_a_3_a_p0_m(u32(I));
- let p_a_I_a_2_m = load_a_p0_a_2_m(u32(I));
- let p_a_I_a_J_m = load_a_p0_a_p1_m(u32(I), u32(J));
- let p_a_3_a_2_m_1 = a[3u].a[2u].m_1;
- let p_a_I_a_J_m_K = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
- let l_a : array<Outer, 4> = conv_arr4_Outer(a);
- let l_a_3 : Outer = conv_Outer(a[3u]);
- let l_a_I : Outer = conv_Outer(a[I]);
- let l_a_3_a : array<Inner, 4> = conv_arr4_Inner(a[3u].a);
- let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
- let l_a_3_a_2 : Inner = conv_Inner(a[3u].a[2u]);
- let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
- let l_a_I_a_2 : Inner = conv_Inner(a[I].a[2u]);
- let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
- let l_a_3_a_2_m : mat3x2<f32> = load_a_3_a_2_m();
- let l_a_3_a_I_m : mat3x2<f32> = load_a_3_a_p0_m(u32(I));
- let l_a_I_a_2_m : mat3x2<f32> = load_a_p0_a_2_m(u32(I));
- let l_a_I_a_J_m : mat3x2<f32> = load_a_p0_a_p1_m(u32(I), u32(J));
- let l_a_3_a_2_m_1 : vec2<f32> = a[3u].a[2u].m_1;
- let l_a_I_a_J_m_K : vec2<f32> = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
- let l_a_2_a_0_m_1_0 : f32 = a[3u].a[2u].m_1[0u];
- let l_a_I_a_J_m_K_I : f32 = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyArray_UniformToStorage_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S, 4>;
-
-@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
-
-fn f() {
- s = u;
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
-
-@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
-
-fn conv_S(val : S_std140) -> S {
- return S(mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn conv_arr4_S(val : array<S_std140, 4u>) -> array<S, 4u> {
- var arr : array<S, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- arr[i] = conv_S(val[i]);
- }
- return arr;
-}
-
-fn f() {
- s = conv_arr4_S(u);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyStruct_UniformToWorkgroup_Mat3x2F32) {
- auto* src = R"(
-struct S {
- v : vec4<i32>,
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S, 4>;
-
-var<workgroup> w : array<S, 4>;
-
-fn f() {
- w[0] = u[1];
-}
-)";
-
- auto* expect = R"(
-struct S {
- v : vec4<i32>,
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- v : vec4<i32>,
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
-
-var<workgroup> w : array<S, 4>;
-
-fn conv_S(val : S_std140) -> S {
- return S(val.v, mat3x2<f32>(val.m_0, val.m_1, val.m_2));
-}
-
-fn f() {
- w[0] = conv_S(u[1u]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyMatrix_UniformToPrivate_Mat3x2F32) {
- auto* src = R"(
-struct S {
- v : vec4<i32>,
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S, 3>;
-
-var<private> p : array<S, 4>;
-
-fn f() {
- p[2].m = u[1].m;
-}
-)";
-
- auto* expect = R"(
-struct S {
- v : vec4<i32>,
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- v : vec4<i32>,
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
-
-var<private> p : array<S, 4>;
-
-fn load_u_1_m() -> mat3x2<f32> {
- let s = &(u[1u]);
- return mat3x2<f32>((*(s)).m_0, (*(s)).m_1, (*(s)).m_2);
-}
-
-fn f() {
- p[2].m = load_u_1_m();
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyColumn_UniformToStorage_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S, 3>;
-
-@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
-
-fn f() {
- s[3].m[1] = u[2].m[0];
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
-
-@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
-
-fn f() {
- s[3].m[1] = u[2u].m_0;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyColumnSwizzle_UniformToWorkgroup_Mat3x2F32) {
- auto* src = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S, 4>;
-
-var<workgroup> w : array<S, 4>;
-
-fn f() {
- w[3].m[1] = u[2].m[0].yx.yx;
-}
-)";
-
- auto* expect = R"(
-struct S {
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
-
-var<workgroup> w : array<S, 4>;
-
-fn f() {
- w[3].m[1] = u[2u].m_0.yx.yx;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayStructMatUniform_CopyScalar_UniformToPrivate_Mat3x2F32) {
- auto* src = R"(
-struct S {
- v : vec4<i32>,
- @size(64)
- m : mat3x2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S, 3>;
-
-var<private> p : array<S, 4>;
-
-fn f() {
- p[3].m[1].x = u[2].m[0].y;
-}
-)";
-
- auto* expect = R"(
-struct S {
- v : vec4<i32>,
- @size(64)
- m : mat3x2<f32>,
-}
-
-struct S_std140 {
- v : vec4<i32>,
- m_0 : vec2<f32>,
- m_1 : vec2<f32>,
- @size(48)
- m_2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
-
-var<private> p : array<S, 4>;
-
-fn f() {
- p[3].m[1].x = u[2u].m_0[1u];
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayMatUniform_LoadArray_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
-
-fn f() {
- let l = a;
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
- var arr : array<mat2x2<f32>, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- arr[i] = conv_mat2x2_f32(val[i]);
- }
- return arr;
-}
-
-fn f() {
- let l = conv_arr3_mat2x2_f32(a);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayMatUniform_LoadMatrix_ConstArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
-
-fn f() {
- let l = a[2];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let l = conv_mat2x2_f32(a[2u]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayMatUniform_LoadMatrix_VariableArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
-
-fn f() {
- let I = 1;
- let l = a[I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let I = 1;
- let l = conv_mat2x2_f32(a[I]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
-
-fn f() {
- let l = a[2][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
-
-fn f() {
- let l = a[2u].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
-
-fn f() {
- let I = 1;
- let l = a[I][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
-
-fn f() {
- let I = 1;
- let l = a[I].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
-
-fn f() {
- let I = 1;
- let l = a[2][I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
-
-fn load_a_2_p0(p0 : u32) -> vec2<f32> {
- switch(p0) {
- case 0u: {
- return a[2u].col0;
- }
- case 1u: {
- return a[2u].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_a_2_p0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<mat2x2<f32>, 3>;
-
-fn f() {
- let I = 1;
- let l = a[I][I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<mat2x2_f32, 3u>;
-
-fn load_a_p0_p1(p0 : u32, p1 : u32) -> vec2<f32> {
- switch(p1) {
- case 0u: {
- return a[p0].col0;
- }
- case 1u: {
- return a[p0].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_a_p0_p1(u32(I), u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructArrayMatUniform_LoadStruct_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s;
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
- var arr : array<mat2x2<f32>, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- arr[i] = conv_mat2x2_f32(val[i]);
- }
- return arr;
-}
-
-fn conv_S(val : S_std140) -> S {
- return S(conv_arr3_mat2x2_f32(val.a));
-}
-
-fn f() {
- let l = conv_S(s);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructArrayMatUniform_LoadArray_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s.a;
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
- var arr : array<mat2x2<f32>, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- arr[i] = conv_mat2x2_f32(val[i]);
- }
- return arr;
-}
-
-fn f() {
- let l = conv_arr3_mat2x2_f32(s.a);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructArrayMatUniform_LoadMatrix_ConstArrayIndex_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s.a[2];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let l = conv_mat2x2_f32(s.a[2u]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, StructArrayMatUniform_LoadMatrix_VariableArrayIndex_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 1;
- let l = s.a[I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let I = 1;
- let l = conv_mat2x2_f32(s.a[I]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- StructArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let l = s.a[2][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn f() {
- let l = s.a[2u].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- StructArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 1;
- let l = s.a[I][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn f() {
- let I = 1;
- let l = s.a[I].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- StructArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 1;
- let l = s.a[2][I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn load_s_a_2_p0(p0 : u32) -> vec2<f32> {
- switch(p0) {
- case 0u: {
- return s.a[2u].col0;
- }
- case 1u: {
- return s.a[2u].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_s_a_2_p0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- StructArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-@group(0) @binding(0) var<uniform> s : S;
-
-fn f() {
- let I = 1;
- let l = s.a[I][I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-struct S {
- a : array<mat2x2<f32>, 3>,
-}
-
-struct S_std140 {
- a : array<mat2x2_f32, 3u>,
-}
-
-@group(0) @binding(0) var<uniform> s : S_std140;
-
-fn load_s_a_p0_p1(p0 : u32, p1 : u32) -> vec2<f32> {
- switch(p1) {
- case 0u: {
- return s.a[p0].col0;
- }
- case 1u: {
- return s.a[p0].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_s_a_p0_p1(u32(I), u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayArrayMatUniform_LoadArrays_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let l = a;
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
- var arr : array<mat2x2<f32>, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- arr[i] = conv_mat2x2_f32(val[i]);
- }
- return arr;
-}
-
-fn conv_arr4_arr3_mat2x2_f32(val : array<array<mat2x2_f32, 3u>, 4u>) -> array<array<mat2x2<f32>, 3u>, 4u> {
- var arr : array<array<mat2x2<f32>, 3u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- arr[i] = conv_arr3_mat2x2_f32(val[i]);
- }
- return arr;
-}
-
-fn f() {
- let l = conv_arr4_arr3_mat2x2_f32(a);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayArrayMatUniform_LoadArray_ConstOuterArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let l = a[3];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
- var arr : array<mat2x2<f32>, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- arr[i] = conv_mat2x2_f32(val[i]);
- }
- return arr;
-}
-
-fn f() {
- let l = conv_arr3_mat2x2_f32(a[3u]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32, ArrayArrayMatUniform_LoadArray_VariableOuterArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let l = a[I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn conv_arr3_mat2x2_f32(val : array<mat2x2_f32, 3u>) -> array<mat2x2<f32>, 3u> {
- var arr : array<mat2x2<f32>, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- arr[i] = conv_mat2x2_f32(val[i]);
- }
- return arr;
-}
-
-fn f() {
- let I = 1;
- let l = conv_arr3_mat2x2_f32(a[I]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_ConstInnerArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let l = a[3][2];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let l = conv_mat2x2_f32(a[3u][2u]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_VariableInnerArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let l = a[3][I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let I = 1;
- let l = conv_mat2x2_f32(a[3u][I]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_ConstInnerArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let l = a[I][2];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let I = 1;
- let l = conv_mat2x2_f32(a[I][2u]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(Std140Test_F32,
- ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_VariableInnerArrayIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let l = a[I][I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn conv_mat2x2_f32(val : mat2x2_f32) -> mat2x2<f32> {
- return mat2x2<f32>(val.col0, val.col1);
-}
-
-fn f() {
- let I = 1;
- let l = conv_mat2x2_f32(a[I][I]);
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let l = a[3][2][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn f() {
- let l = a[3u][2u].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let l = a[3][2][I];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn load_a_3_2_p0(p0 : u32) -> vec2<f32> {
- switch(p0) {
- case 0u: {
- return a[3u][2u].col0;
- }
- case 1u: {
- return a[3u][2u].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let l = load_a_3_2_p0(u32(I));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let l = a[3][I][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn f() {
- let I = 1;
- let l = a[3u][I].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let J = 2;
- let l = a[3][I][J];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn load_a_3_p0_p1(p0 : u32, p1 : u32) -> vec2<f32> {
- switch(p1) {
- case 0u: {
- return a[3u][p0].col0;
- }
- case 1u: {
- return a[3u][p0].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let J = 2;
- let l = load_a_3_p0_p1(u32(I), u32(J));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let l = a[I][2][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn f() {
- let I = 1;
- let l = a[I][2u].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let J = 2;
- let l = a[I][2][J];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn load_a_p0_2_p1(p0 : u32, p1 : u32) -> vec2<f32> {
- switch(p1) {
- case 0u: {
- return a[p0][2u].col0;
- }
- case 1u: {
- return a[p0][2u].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 1;
- let J = 2;
- let l = load_a_p0_2_p1(u32(I), u32(J));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 1;
- let J = 2;
- let l = a[I][J][1];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn f() {
- let I = 1;
- let J = 2;
- let l = a[I][J].col1;
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(
- Std140Test_F32,
- ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex_Mat2x2F32) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2<f32>, 3>, 4>;
-
-fn f() {
- let I = 0;
- let J = 1;
- let K = 2;
- let l = a[I][J][K];
-}
-)";
-
- auto* expect = R"(
-struct mat2x2_f32 {
- col0 : vec2<f32>,
- col1 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> a : array<array<mat2x2_f32, 3u>, 4u>;
-
-fn load_a_p0_p1_p2(p0 : u32, p1 : u32, p2 : u32) -> vec2<f32> {
- switch(p2) {
- case 0u: {
- return a[p0][p1].col0;
- }
- case 1u: {
- return a[p0][p1].col1;
- }
- default: {
- return vec2<f32>();
- }
- }
-}
-
-fn f() {
- let I = 0;
- let J = 1;
- let K = 2;
- let l = load_a_p0_p1_p2(u32(I), u32(J), u32(K));
-}
-)";
-
- auto got = Run<Std140>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
} // namespace
} // namespace tint::transform
diff --git a/src/tint/transform/truncate_interstage_variables.cc b/src/tint/transform/truncate_interstage_variables.cc
index a5e7256..30237bc 100644
--- a/src/tint/transform/truncate_interstage_variables.cc
+++ b/src/tint/transform/truncate_interstage_variables.cc
@@ -161,7 +161,7 @@
ctx.ReplaceAll(
[&](const ast::ReturnStatement* return_statement) -> const ast::ReturnStatement* {
auto* return_sem = sem.Get(return_statement);
- if (auto* mapping_fn_sym =
+ if (auto mapping_fn_sym =
entry_point_functions_to_truncate_functions.Find(return_sem->Function())) {
return b.Return(return_statement->source,
b.Call(*mapping_fn_sym, ctx.Clone(return_statement->value)));
diff --git a/src/tint/transform/unshadow.cc b/src/tint/transform/unshadow.cc
index 93ce595..8d2b876 100644
--- a/src/tint/transform/unshadow.cc
+++ b/src/tint/transform/unshadow.cc
@@ -97,7 +97,7 @@
ctx.ReplaceAll(
[&](const ast::IdentifierExpression* ident) -> const tint::ast::IdentifierExpression* {
if (auto* user = sem.Get<sem::VariableUser>(ident)) {
- if (auto* renamed = renamed_to.Find(user->Variable())) {
+ if (auto renamed = renamed_to.Find(user->Variable())) {
return b.Expr(*renamed);
}
}
diff --git a/src/tint/transform/utils/hoist_to_decl_before.cc b/src/tint/transform/utils/hoist_to_decl_before.cc
index e0b35a1..ede1986 100644
--- a/src/tint/transform/utils/hoist_to_decl_before.cc
+++ b/src/tint/transform/utils/hoist_to_decl_before.cc
@@ -38,23 +38,39 @@
/// @copydoc HoistToDeclBefore::Add()
bool Add(const sem::Expression* before_expr,
const ast::Expression* expr,
- bool as_let,
+ VariableKind kind,
const char* decl_name) {
auto name = b.Symbols().New(decl_name);
- if (as_let) {
- auto builder = [this, expr, name] {
- return b.Decl(b.Let(name, ctx.CloneWithoutTransform(expr)));
- };
- if (!InsertBeforeImpl(before_expr->Stmt(), std::move(builder))) {
- return false;
+ switch (kind) {
+ case VariableKind::kLet: {
+ auto builder = [this, expr, name] {
+ return b.Decl(b.Let(name, ctx.CloneWithoutTransform(expr)));
+ };
+ if (!InsertBeforeImpl(before_expr->Stmt(), std::move(builder))) {
+ return false;
+ }
+ break;
}
- } else {
- auto builder = [this, expr, name] {
- return b.Decl(b.Var(name, ctx.CloneWithoutTransform(expr)));
- };
- if (!InsertBeforeImpl(before_expr->Stmt(), std::move(builder))) {
- return false;
+
+ case VariableKind::kVar: {
+ auto builder = [this, expr, name] {
+ return b.Decl(b.Var(name, ctx.CloneWithoutTransform(expr)));
+ };
+ if (!InsertBeforeImpl(before_expr->Stmt(), std::move(builder))) {
+ return false;
+ }
+ break;
+ }
+
+ case VariableKind::kConst: {
+ auto builder = [this, expr, name] {
+ return b.Decl(b.Const(name, ctx.CloneWithoutTransform(expr)));
+ };
+ if (!InsertBeforeImpl(before_expr->Stmt(), std::move(builder))) {
+ return false;
+ }
+ break;
}
}
@@ -119,7 +135,7 @@
/// automatically called.
/// @warning the returned reference is invalid if this is called a second time, or the
/// #for_loops map is mutated.
- LoopInfo& ForLoop(const sem::ForLoopStatement* for_loop) {
+ auto ForLoop(const sem::ForLoopStatement* for_loop) {
if (for_loops.IsEmpty()) {
RegisterForLoopTransform();
}
@@ -131,7 +147,7 @@
/// automatically called.
/// @warning the returned reference is invalid if this is called a second time, or the
/// #for_loops map is mutated.
- LoopInfo& WhileLoop(const sem::WhileStatement* while_loop) {
+ auto WhileLoop(const sem::WhileStatement* while_loop) {
if (while_loops.IsEmpty()) {
RegisterWhileLoopTransform();
}
@@ -143,7 +159,7 @@
/// automatically called.
/// @warning the returned reference is invalid if this is called a second time, or the
/// #else_ifs map is mutated.
- ElseIfInfo& ElseIf(const ast::IfStatement* else_if) {
+ auto ElseIf(const ast::IfStatement* else_if) {
if (else_ifs.IsEmpty()) {
RegisterElseIfTransform();
}
@@ -156,7 +172,7 @@
auto& sem = ctx.src->Sem();
if (auto* fl = sem.Get(stmt)) {
- if (auto* info = for_loops.Find(fl)) {
+ if (auto info = for_loops.Find(fl)) {
auto* for_loop = fl->Declaration();
// For-loop needs to be decomposed to a loop.
// Build the loop body's statements.
@@ -206,7 +222,7 @@
auto& sem = ctx.src->Sem();
if (auto* w = sem.Get(stmt)) {
- if (auto* info = while_loops.Find(w)) {
+ if (auto info = while_loops.Find(w)) {
auto* while_loop = w->Declaration();
// While needs to be decomposed to a loop.
// Build the loop body's statements.
@@ -243,7 +259,7 @@
void RegisterElseIfTransform() const {
// Decompose 'else-if' statements into 'else { if }' blocks.
ctx.ReplaceAll([&](const ast::IfStatement* stmt) -> const ast::Statement* {
- if (auto* info = else_ifs.Find(stmt)) {
+ if (auto info = else_ifs.Find(stmt)) {
// Build the else block's body statements, starting with let decls for the
// conditional expression.
auto body_stmts = Build(info->cond_decls);
@@ -275,10 +291,10 @@
if (else_if && else_if->Parent()->Is<sem::IfStatement>()) {
// Insertion point is an 'else if' condition.
// Need to convert 'else if' to 'else { if }'.
- auto& else_if_info = ElseIf(else_if->Declaration());
+ auto else_if_info = ElseIf(else_if->Declaration());
// Index the map to convert this else if, even if `stmt` is nullptr.
- auto& decls = else_if_info.cond_decls;
+ auto& decls = else_if_info->cond_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
}
@@ -290,7 +306,7 @@
// For-loop needs to be decomposed to a loop.
// Index the map to convert this for-loop, even if `stmt` is nullptr.
- auto& decls = ForLoop(fl).cond_decls;
+ auto& decls = ForLoop(fl)->cond_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
}
@@ -302,7 +318,7 @@
// While needs to be decomposed to a loop.
// Index the map to convert this while, even if `stmt` is nullptr.
- auto& decls = WhileLoop(w).cond_decls;
+ auto& decls = WhileLoop(w)->cond_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
}
@@ -338,7 +354,7 @@
// For-loop needs to be decomposed to a loop.
// Index the map to convert this for-loop, even if `stmt` is nullptr.
- auto& decls = ForLoop(fl).cont_decls;
+ auto& decls = ForLoop(fl)->cont_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
}
@@ -361,9 +377,9 @@
bool HoistToDeclBefore::Add(const sem::Expression* before_expr,
const ast::Expression* expr,
- bool as_let,
+ VariableKind kind,
const char* decl_name) {
- return state_->Add(before_expr, expr, as_let, decl_name);
+ return state_->Add(before_expr, expr, kind, decl_name);
}
bool HoistToDeclBefore::InsertBefore(const sem::Statement* before_stmt,
diff --git a/src/tint/transform/utils/hoist_to_decl_before.h b/src/tint/transform/utils/hoist_to_decl_before.h
index d9a8a8a..4d6a808 100644
--- a/src/tint/transform/utils/hoist_to_decl_before.h
+++ b/src/tint/transform/utils/hoist_to_decl_before.h
@@ -38,16 +38,23 @@
/// StmtBuilder is a builder of an AST statement
using StmtBuilder = std::function<const ast::Statement*()>;
+ /// VariableKind is either a var, let or const
+ enum class VariableKind {
+ kVar,
+ kLet,
+ kConst,
+ };
+
/// Hoists @p expr to a `let` or `var` with optional `decl_name`, inserting it
/// before @p before_expr.
/// @param before_expr expression to insert `expr` before
/// @param expr expression to hoist
- /// @param as_let hoist to `let` if true, otherwise to `var`
+ /// @param kind variable kind to hoist to
/// @param decl_name optional name to use for the variable/constant name
/// @return true on success
bool Add(const sem::Expression* before_expr,
const ast::Expression* expr,
- bool as_let,
+ VariableKind kind,
const char* decl_name = "");
/// Inserts @p stmt before @p before_stmt, possibly converting 'for-loop's to 'loop's if
diff --git a/src/tint/transform/utils/hoist_to_decl_before_test.cc b/src/tint/transform/utils/hoist_to_decl_before_test.cc
index 7b45e01..c5dca5d 100644
--- a/src/tint/transform/utils/hoist_to_decl_before_test.cc
+++ b/src/tint/transform/utils/hoist_to_decl_before_test.cc
@@ -44,7 +44,7 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kLet);
ctx.Clone();
Program cloned(std::move(cloned_b));
@@ -75,14 +75,14 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kVar);
ctx.Clone();
Program cloned(std::move(cloned_b));
auto* expect = R"(
fn f() {
- let tint_symbol = 1i;
+ var tint_symbol = 1i;
for(var a = tint_symbol; true; ) {
}
}
@@ -93,12 +93,12 @@
TEST_F(HoistToDeclBeforeTest, ForLoopCond) {
// fn f() {
- // var a : bool;
+ // const a = true;
// for(; a; ) {
// }
// }
ProgramBuilder b;
- auto* var = b.Decl(b.Var("a", b.ty.bool_()));
+ auto* var = b.Decl(b.Const("a", b.Expr(true)));
auto* expr = b.Expr("a");
auto* s = b.For(nullptr, expr, nullptr, b.Block());
b.Func("f", utils::Empty, b.ty.void_(), utils::Vector{var, s});
@@ -109,16 +109,16 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kConst);
ctx.Clone();
Program cloned(std::move(cloned_b));
auto* expect = R"(
fn f() {
- var a : bool;
+ const a = true;
loop {
- let tint_symbol = a;
+ const tint_symbol = a;
if (!(tint_symbol)) {
break;
}
@@ -147,7 +147,7 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kLet);
ctx.Clone();
Program cloned(std::move(cloned_b));
@@ -190,7 +190,7 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kVar);
ctx.Clone();
Program cloned(std::move(cloned_b));
@@ -199,7 +199,7 @@
fn f() {
var a : bool;
loop {
- let tint_symbol = a;
+ var tint_symbol = a;
if (!(tint_symbol)) {
break;
}
@@ -214,14 +214,14 @@
TEST_F(HoistToDeclBeforeTest, ElseIf) {
// fn f() {
- // var a : bool;
+ // const a = true;
// if (true) {
// } else if (a) {
// } else {
// }
// }
ProgramBuilder b;
- auto* var = b.Decl(b.Var("a", b.ty.bool_()));
+ auto* var = b.Decl(b.Const("a", b.Expr(true)));
auto* expr = b.Expr("a");
auto* s = b.If(b.Expr(true), b.Block(), //
b.Else(b.If(expr, b.Block(), //
@@ -234,17 +234,17 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kConst);
ctx.Clone();
Program cloned(std::move(cloned_b));
auto* expect = R"(
fn f() {
- var a : bool;
+ const a = true;
if (true) {
} else {
- let tint_symbol = a;
+ const tint_symbol = a;
if (tint_symbol) {
} else {
}
@@ -272,7 +272,7 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kLet);
ctx.Clone();
Program cloned(std::move(cloned_b));
@@ -306,7 +306,7 @@
HoistToDeclBefore hoistToDeclBefore(ctx);
auto* sem_expr = ctx.src->Sem().Get(expr);
- hoistToDeclBefore.Add(sem_expr, expr, true);
+ hoistToDeclBefore.Add(sem_expr, expr, HoistToDeclBefore::VariableKind::kVar);
ctx.Clone();
Program cloned(std::move(cloned_b));
@@ -314,7 +314,7 @@
auto* expect = R"(
fn f() {
var a : array<array<i32, 10u>, 10i>;
- let tint_symbol = a[0i][0i];
+ var tint_symbol = a[0i][0i];
var b = tint_symbol;
}
)";
diff --git a/src/tint/transform/var_for_dynamic_index.cc b/src/tint/transform/var_for_dynamic_index.cc
index 81af013..c2fb0a5 100644
--- a/src/tint/transform/var_for_dynamic_index.cc
+++ b/src/tint/transform/var_for_dynamic_index.cc
@@ -54,7 +54,8 @@
// TODO(bclayton): group multiple accesses in the same object.
// e.g. arr[i] + arr[i+1] // Don't create two vars for this
- return hoist_to_decl_before.Add(indexed, object_expr, false, "var_for_index");
+ return hoist_to_decl_before.Add(indexed, object_expr, HoistToDeclBefore::VariableKind::kVar,
+ "var_for_index");
};
bool index_accessor_found = false;
diff --git a/src/tint/utils/hashmap.h b/src/tint/utils/hashmap.h
index 1040e0c..19a5abe 100644
--- a/src/tint/utils/hashmap.h
+++ b/src/tint/utils/hashmap.h
@@ -47,6 +47,67 @@
/// Result of Add()
using AddResult = typename Base::PutResult;
+ /// Reference is returned by Hashmap::Find(), and performs dynamic Hashmap lookups.
+ /// The value returned by the Reference reflects the current state of the Hashmap, and so the
+ /// referenced value may change, or transition between valid or invalid based on the current
+ /// state of the Hashmap.
+ template <bool IS_CONST>
+ class ReferenceT {
+ /// `const Value` if IS_CONST, or `Value` if !IS_CONST
+ using T = std::conditional_t<IS_CONST, const Value, Value>;
+
+ /// `const Hashmap` if IS_CONST, or `Hashmap` if !IS_CONST
+ using Map = std::conditional_t<IS_CONST, const Hashmap, Hashmap>;
+
+ public:
+ /// @returns true if the reference is valid.
+ operator bool() const { return Get() != nullptr; }
+
+ /// @returns the pointer to the Value, or nullptr if the reference is invalid.
+ operator T*() const { return Get(); }
+
+ /// @returns the pointer to the Value
+ /// @warning if the Hashmap does not contain a value for the reference, then this will
+ /// trigger a TINT_ASSERT, or invalid pointer dereference.
+ T* operator->() const {
+ auto* hashmap_reference_lookup = Get();
+ TINT_ASSERT(Utils, hashmap_reference_lookup != nullptr);
+ return hashmap_reference_lookup;
+ }
+
+ /// @returns the pointer to the Value, or nullptr if the reference is invalid.
+ T* Get() const {
+ auto generation = map_.Generation();
+ if (generation_ != generation) {
+ cached_ = map_.Lookup(key_);
+ generation_ = generation;
+ }
+ return cached_;
+ }
+
+ private:
+ friend Hashmap;
+
+ /// Constructor
+ ReferenceT(Map& map, const Key& key)
+ : map_(map), key_(key), cached_(nullptr), generation_(map.Generation() - 1) {}
+
+ /// Constructor
+ ReferenceT(Map& map, const Key& key, T* value)
+ : map_(map), key_(key), cached_(value), generation_(map.Generation()) {}
+
+ Map& map_;
+ const Key key_;
+ mutable T* cached_ = nullptr;
+ mutable size_t generation_ = 0;
+ };
+
+ /// A mutable reference returned by Find()
+ using Reference = ReferenceT</*IS_CONST*/ false>;
+
+ /// An immutable reference returned by Find()
+ using ConstReference = ReferenceT</*IS_CONST*/ true>;
+
/// Adds a value to the map, if the map does not already contain an entry with the key @p key.
/// @param key the entry key.
/// @param value the value of the entry to add to the map.
@@ -108,25 +169,28 @@
/// @param key the entry's key value to search for.
/// @returns the value of the entry.
template <typename K>
- Value& GetOrZero(K&& key) {
+ Reference GetOrZero(K&& key) {
auto res = Add(std::forward<K>(key), Value{});
- return *res.value;
+ return Reference(*this, key, res.value);
}
/// @param key the key to search for.
- /// @returns a pointer to the entry that is equal to the given value, or nullptr if the map does
- /// not contain the given value.
- const Value* Find(const Key& key) const {
+ /// @returns a reference to the entry that is equal to the given value.
+ Reference Find(const Key& key) { return Reference(*this, key); }
+
+ /// @param key the key to search for.
+ /// @returns a reference to the entry that is equal to the given value.
+ ConstReference Find(const Key& key) const { return ConstReference(*this, key); }
+
+ private:
+ Value* Lookup(const Key& key) {
if (auto [found, index] = this->IndexOf(key); found) {
return &this->slots_[index].entry->value;
}
return nullptr;
}
- /// @param key the key to search for.
- /// @returns a pointer to the entry that is equal to the given value, or nullptr if the map does
- /// not contain the given value.
- Value* Find(const Key& key) {
+ const Value* Lookup(const Key& key) const {
if (auto [found, index] = this->IndexOf(key); found) {
return &this->slots_[index].entry->value;
}
diff --git a/src/tint/utils/hashmap_test.cc b/src/tint/utils/hashmap_test.cc
index 77421cf..34a93e6 100644
--- a/src/tint/utils/hashmap_test.cc
+++ b/src/tint/utils/hashmap_test.cc
@@ -90,6 +90,71 @@
EXPECT_EQ(map.Generation(), 5u);
}
+TEST(Hashmap, Index) {
+ Hashmap<int, std::string, 4> map;
+ auto zero = map.Find(0);
+ EXPECT_FALSE(zero);
+
+ map.Add(3, "three");
+ auto three = map.Find(3);
+ map.Add(2, "two");
+ auto two = map.Find(2);
+ map.Add(4, "four");
+ auto four = map.Find(4);
+ map.Add(8, "eight");
+ auto eight = map.Find(8);
+
+ EXPECT_FALSE(zero);
+ ASSERT_TRUE(three);
+ ASSERT_TRUE(two);
+ ASSERT_TRUE(four);
+ ASSERT_TRUE(eight);
+
+ EXPECT_EQ(*three, "three");
+ EXPECT_EQ(*two, "two");
+ EXPECT_EQ(*four, "four");
+ EXPECT_EQ(*eight, "eight");
+
+ map.Add(0, "zero"); // Note: Find called before Add() is okay!
+
+ map.Add(5, "five");
+ auto five = map.Find(5);
+ map.Add(6, "six");
+ auto six = map.Find(6);
+ map.Add(1, "one");
+ auto one = map.Find(1);
+ map.Add(7, "seven");
+ auto seven = map.Find(7);
+
+ ASSERT_TRUE(zero);
+ ASSERT_TRUE(three);
+ ASSERT_TRUE(two);
+ ASSERT_TRUE(four);
+ ASSERT_TRUE(eight);
+ ASSERT_TRUE(five);
+ ASSERT_TRUE(six);
+ ASSERT_TRUE(one);
+ ASSERT_TRUE(seven);
+
+ EXPECT_EQ(*zero, "zero");
+ EXPECT_EQ(*three, "three");
+ EXPECT_EQ(*two, "two");
+ EXPECT_EQ(*four, "four");
+ EXPECT_EQ(*eight, "eight");
+ EXPECT_EQ(*five, "five");
+ EXPECT_EQ(*six, "six");
+ EXPECT_EQ(*one, "one");
+ EXPECT_EQ(*seven, "seven");
+
+ map.Remove(2);
+ map.Remove(8);
+ map.Remove(1);
+
+ EXPECT_FALSE(two);
+ EXPECT_FALSE(eight);
+ EXPECT_FALSE(one);
+}
+
TEST(Hashmap, Iterator) {
using Map = Hashmap<int, std::string, 8>;
using Entry = typename Map::Entry;
diff --git a/src/tint/writer/glsl/generator_impl_builtin_test.cc b/src/tint/writer/glsl/generator_impl_builtin_test.cc
index 7d0a72e..d4b7053 100644
--- a/src/tint/writer/glsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/glsl/generator_impl_builtin_test.cc
@@ -425,13 +425,13 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-struct modf_result {
+struct modf_result_f32 {
float fract;
float whole;
};
-modf_result tint_modf(float param_0) {
- modf_result result;
+modf_result_f32 tint_modf(float param_0) {
+ modf_result_f32 result;
result.fract = modf(param_0, result.whole);
return result;
}
@@ -439,7 +439,7 @@
void test_function() {
float f = 1.5f;
- modf_result v = tint_modf(f);
+ modf_result_f32 v = tint_modf(f);
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -496,13 +496,13 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-struct modf_result_vec3 {
+struct modf_result_vec3_f32 {
vec3 fract;
vec3 whole;
};
-modf_result_vec3 tint_modf(vec3 param_0) {
- modf_result_vec3 result;
+modf_result_vec3_f32 tint_modf(vec3 param_0) {
+ modf_result_vec3_f32 result;
result.fract = modf(param_0, result.whole);
return result;
}
@@ -510,7 +510,7 @@
void test_function() {
vec3 f = vec3(1.5f, 2.5f, 3.5f);
- modf_result_vec3 v = tint_modf(f);
+ modf_result_vec3_f32 v = tint_modf(f);
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -566,14 +566,14 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-struct modf_result {
+struct modf_result_f32 {
float fract;
float whole;
};
void test_function() {
- modf_result v = modf_result(0.5f, 1.0f);
+ modf_result_f32 v = modf_result_f32(0.5f, 1.0f);
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -621,14 +621,14 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-struct modf_result_vec3 {
+struct modf_result_vec3_f32 {
vec3 fract;
vec3 whole;
};
void test_function() {
- modf_result_vec3 v = modf_result_vec3(vec3(0.5f), vec3(1.0f, 2.0f, 3.0f));
+ modf_result_vec3_f32 v = modf_result_vec3_f32(vec3(0.5f), vec3(1.0f, 2.0f, 3.0f));
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -668,29 +668,30 @@
)");
}
-TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Scalar_f32) {
- auto* call = Call("frexp", 1_f);
- WrapInFunction(CallStmt(call));
+TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Frexp_Scalar_f32) {
+ WrapInFunction(Var("f", Expr(1_f)), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-struct frexp_result {
+struct frexp_result_f32 {
float fract;
int exp;
};
-frexp_result tint_frexp(float param_0) {
- frexp_result result;
+frexp_result_f32 tint_frexp(float param_0) {
+ frexp_result_f32 result;
result.fract = frexp(param_0, result.exp);
return result;
}
void test_function() {
- tint_frexp(1.0f);
+ float f = 1.0f;
+ frexp_result_f32 v = tint_frexp(f);
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -701,11 +702,11 @@
)");
}
-TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Scalar_f16) {
+TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Frexp_Scalar_f16) {
Enable(ast::Extension::kF16);
- auto* call = Call("frexp", 1_h);
- WrapInFunction(CallStmt(call));
+ WrapInFunction(Var("f", Expr(1_h)), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -726,7 +727,8 @@
void test_function() {
- tint_frexp(1.0hf);
+ float16_t f = 1.0hf;
+ frexp_result_f16 v = tint_frexp(f);
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -737,29 +739,30 @@
)");
}
-TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Vector_f32) {
- auto* call = Call("frexp", vec3<f32>());
- WrapInFunction(CallStmt(call));
+TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f32) {
+ WrapInFunction(Var("f", Expr(vec3<f32>())), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-struct frexp_result_vec3 {
+struct frexp_result_vec3_f32 {
vec3 fract;
ivec3 exp;
};
-frexp_result_vec3 tint_frexp(vec3 param_0) {
- frexp_result_vec3 result;
+frexp_result_vec3_f32 tint_frexp(vec3 param_0) {
+ frexp_result_vec3_f32 result;
result.fract = frexp(param_0, result.exp);
return result;
}
void test_function() {
- tint_frexp(vec3(0.0f));
+ vec3 f = vec3(0.0f);
+ frexp_result_vec3_f32 v = tint_frexp(f);
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -770,11 +773,11 @@
)");
}
-TEST_F(GlslGeneratorImplTest_Builtin, Frexp_Vector_f16) {
+TEST_F(GlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f16) {
Enable(ast::Extension::kF16);
- auto* call = Call("frexp", vec3<f16>());
- WrapInFunction(CallStmt(call));
+ WrapInFunction(Var("f", Expr(vec3<f16>())), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -795,7 +798,118 @@
void test_function() {
- tint_frexp(f16vec3(0.0hf));
+ f16vec3 f = f16vec3(0.0hf);
+ frexp_result_vec3_f16 v = tint_frexp(f);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ test_function();
+ return;
+}
+)");
+}
+
+TEST_F(GlslGeneratorImplTest_Builtin, Const_Frexp_Scalar_f32) {
+ WrapInFunction(Decl(Let("v", Call("frexp", 1_f))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#version 310 es
+
+struct frexp_result_f32 {
+ float fract;
+ int exp;
+};
+
+
+void test_function() {
+ frexp_result_f32 v = frexp_result_f32(0.5f, 1);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ test_function();
+ return;
+}
+)");
+}
+
+TEST_F(GlslGeneratorImplTest_Builtin, Const_Frexp_Scalar_f16) {
+ Enable(ast::Extension::kF16);
+
+ WrapInFunction(Decl(Let("v", Call("frexp", 1_h))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#version 310 es
+#extension GL_AMD_gpu_shader_half_float : require
+
+struct frexp_result_f16 {
+ float16_t fract;
+ int exp;
+};
+
+
+void test_function() {
+ frexp_result_f16 v = frexp_result_f16(0.5hf, 1);
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ test_function();
+ return;
+}
+)");
+}
+
+TEST_F(GlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f32) {
+ WrapInFunction(Decl(Let("v", Call("frexp", vec3<f32>()))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#version 310 es
+
+struct frexp_result_vec3_f32 {
+ vec3 fract;
+ ivec3 exp;
+};
+
+
+void test_function() {
+ frexp_result_vec3_f32 v = frexp_result_vec3_f32(vec3(0.0f), ivec3(0));
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ test_function();
+ return;
+}
+)");
+}
+
+TEST_F(GlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f16) {
+ Enable(ast::Extension::kF16);
+
+ WrapInFunction(Decl(Let("v", Call("frexp", vec3<f16>()))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#version 310 es
+#extension GL_AMD_gpu_shader_half_float : require
+
+struct frexp_result_vec3_f16 {
+ f16vec3 fract;
+ ivec3 exp;
+};
+
+
+void test_function() {
+ frexp_result_vec3_f16 v = frexp_result_vec3_f16(f16vec3(0.0hf), ivec3(0));
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -815,20 +929,8 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
-struct frexp_result {
- float fract;
- int exp;
-};
-
-frexp_result tint_frexp(float param_0) {
- frexp_result result;
- result.fract = frexp(param_0, result.exp);
- return result;
-}
-
-
void test_function() {
- float tint_symbol = tint_frexp(1.0f).fract;
+ float tint_symbol = 0.5f;
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index dcad1b5..1e786da 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -1097,31 +1097,62 @@
const auto& args = expr->args;
auto* offset_arg = builder_.Sem().Get(args[1]);
- uint32_t scalar_offset_value = 0;
- std::string scalar_offset_expr;
+ // offset in bytes
+ uint32_t scalar_offset_bytes = 0;
+ // offset in uint (4 bytes)
+ uint32_t scalar_offset_index = 0;
+ // expression to calculate offset in bytes
+ std::string scalar_offset_bytes_expr;
+ // expression to calculate offset in uint, by dividing scalar_offset_bytes_expr by 4
+ std::string scalar_offset_index_expr;
+ // expression to calculate offset in uint, independently
+ std::string scalar_offset_index_unified_expr;
- // If true, use scalar_offset_value, otherwise use scalar_offset_expr
+ // If true, use scalar_offset_index, otherwise use scalar_offset_index_expr
bool scalar_offset_constant = false;
if (auto* val = offset_arg->ConstantValue()) {
TINT_ASSERT(Writer, val->Type()->Is<sem::U32>());
- scalar_offset_value = static_cast<uint32_t>(std::get<AInt>(val->Value()));
- scalar_offset_value /= 4; // bytes -> scalar index
+ scalar_offset_bytes = static_cast<uint32_t>(std::get<AInt>(val->Value()));
+ scalar_offset_index = scalar_offset_bytes / 4; // bytes -> scalar index
scalar_offset_constant = true;
}
+ // If true, scalar_offset_bytes or scalar_offset_bytes_expr should be used, otherwise only use
+ // scalar_offset_index or scalar_offset_index_unified_expr. Currently only loading f16 scalar
+ // require using offset in bytes.
+ const bool need_offset_in_bytes =
+ intrinsic->type == transform::DecomposeMemoryAccess::Intrinsic::DataType::kF16;
+
if (!scalar_offset_constant) {
// UBO offset not compile-time known.
// Calculate the scalar offset into a temporary.
- scalar_offset_expr = UniqueIdentifier("scalar_offset");
- auto pre = line();
- pre << "const uint " << scalar_offset_expr << " = (";
- if (!EmitExpression(pre, args[1])) { // offset
- return false;
+ if (need_offset_in_bytes) {
+ scalar_offset_bytes_expr = UniqueIdentifier("scalar_offset_bytes");
+ scalar_offset_index_expr = UniqueIdentifier("scalar_offset_index");
+ {
+ auto pre = line();
+ pre << "const uint " << scalar_offset_bytes_expr << " = (";
+ if (!EmitExpression(pre, args[1])) { // offset
+ return false;
+ }
+ pre << ");";
+ }
+ line() << "const uint " << scalar_offset_index_expr << " = " << scalar_offset_bytes_expr
+ << " / 4;";
+ } else {
+ scalar_offset_index_unified_expr = UniqueIdentifier("scalar_offset");
+ auto pre = line();
+ pre << "const uint " << scalar_offset_index_unified_expr << " = (";
+ if (!EmitExpression(pre, args[1])) { // offset
+ return false;
+ }
+ pre << ") / 4;";
}
- pre << ") / 4;";
}
+ constexpr const char swizzle[] = {'x', 'y', 'z', 'w'};
+
using Op = transform::DecomposeMemoryAccess::Intrinsic::Op;
using DataType = transform::DecomposeMemoryAccess::Intrinsic::DataType;
switch (intrinsic->op) {
@@ -1132,27 +1163,28 @@
out << ")";
return result;
};
- auto load_scalar = [&]() {
- if (!EmitExpression(out, args[0])) { // buffer
+ auto load_u32_to = [&](std::ostream& target) {
+ if (!EmitExpression(target, args[0])) { // buffer
return false;
}
if (scalar_offset_constant) {
- char swizzle[] = {'x', 'y', 'z', 'w'};
- out << "[" << (scalar_offset_value / 4) << "]."
- << swizzle[scalar_offset_value & 3];
+ target << "[" << (scalar_offset_index / 4) << "]."
+ << swizzle[scalar_offset_index & 3];
} else {
- out << "[" << scalar_offset_expr << " / 4][" << scalar_offset_expr << " % 4]";
+ target << "[" << scalar_offset_index_unified_expr << " / 4]["
+ << scalar_offset_index_unified_expr << " % 4]";
}
return true;
};
+ auto load_u32 = [&] { return load_u32_to(out); };
// Has a minimum alignment of 8 bytes, so is either .xy or .zw
- auto load_vec2 = [&] {
+ auto load_vec2_u32_to = [&](std::ostream& target) {
if (scalar_offset_constant) {
- if (!EmitExpression(out, args[0])) { // buffer
+ if (!EmitExpression(target, args[0])) { // buffer
return false;
}
- out << "[" << (scalar_offset_value / 4) << "]";
- out << ((scalar_offset_value & 2) == 0 ? ".xy" : ".zw");
+ target << "[" << (scalar_offset_index / 4) << "]";
+ target << ((scalar_offset_index & 2) == 0 ? ".xy" : ".zw");
} else {
std::string ubo_load = UniqueIdentifier("ubo_load");
{
@@ -1161,58 +1193,190 @@
if (!EmitExpression(pre, args[0])) { // buffer
return false;
}
- pre << "[" << scalar_offset_expr << " / 4];";
+ pre << "[" << scalar_offset_index_unified_expr << " / 4];";
}
- out << "((" << scalar_offset_expr << " & 2) ? " << ubo_load
- << ".zw : " << ubo_load << ".xy)";
+ target << "((" << scalar_offset_index_unified_expr << " & 2) ? " << ubo_load
+ << ".zw : " << ubo_load << ".xy)";
}
return true;
};
+ auto load_vec2_u32 = [&] { return load_vec2_u32_to(out); };
// vec4 has a minimum alignment of 16 bytes, easiest case
- auto load_vec4 = [&] {
+ auto load_vec4_u32 = [&] {
if (!EmitExpression(out, args[0])) { // buffer
return false;
}
if (scalar_offset_constant) {
- out << "[" << (scalar_offset_value / 4) << "]";
+ out << "[" << (scalar_offset_index / 4) << "]";
} else {
- out << "[" << scalar_offset_expr << " / 4]";
+ out << "[" << scalar_offset_index_unified_expr << " / 4]";
}
return true;
};
// vec3 has a minimum alignment of 16 bytes, so is just a .xyz swizzle
- auto load_vec3 = [&] {
- if (!load_vec4()) {
+ auto load_vec3_u32 = [&] {
+ if (!load_vec4_u32()) {
return false;
}
out << ".xyz";
return true;
};
+ auto load_scalar_f16 = [&] {
+ // offset bytes = 4k, ((buffer[index].x) & 0xFFFF)
+ // offset bytes = 4k+2, ((buffer[index].x >> 16) & 0xFFFF)
+ out << "float16_t(f16tof32(((";
+ if (!EmitExpression(out, args[0])) { // buffer
+ return false;
+ }
+ if (scalar_offset_constant) {
+ out << "[" << (scalar_offset_index / 4) << "]."
+ << swizzle[scalar_offset_index & 3];
+ // WGSL spec ensure little endian memory layout.
+ if (scalar_offset_bytes % 4 == 0) {
+ out << ") & 0xFFFF)";
+ } else {
+ out << " >> 16) & 0xFFFF)";
+ }
+ } else {
+ out << "[" << scalar_offset_index_expr << " / 4][" << scalar_offset_index_expr
+ << " % 4] >> (" << scalar_offset_bytes_expr
+ << " % 4 == 0 ? 0 : 16)) & 0xFFFF)";
+ }
+ out << "))";
+ return true;
+ };
+ auto load_vec2_f16 = [&] {
+ // vec2<f16> is aligned to 4 bytes
+ // Preclude code load the vec2<f16> data as a uint:
+ // uint ubo_load = buffer[id0][id1];
+ // Loading code convert it to vec2<f16>:
+ // vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)),
+ // float16_t(f16tof32(ubo_load >> 16)))
+ std::string ubo_load = UniqueIdentifier("ubo_load");
+ {
+ auto pre = line();
+ // Load the 4 bytes f16 vector as an uint
+ pre << "uint " << ubo_load << " = ";
+ if (!load_u32_to(pre)) {
+ return false;
+ }
+ pre << ";";
+ }
+ out << "vector<float16_t, 2>(float16_t(f16tof32(" << ubo_load
+ << " & 0xFFFF)), float16_t(f16tof32(" << ubo_load << " >> 16)))";
+ return true;
+ };
+ auto load_vec3_f16 = [&] {
+ // vec3<f16> is aligned to 8 bytes
+ // Preclude code load the vec3<f16> data as uint2 and convert its elements to
+ // float16_t:
+ // uint2 ubo_load = buffer[id0].xy;
+ // /* The low 8 bits of two uint are the x and z elements of vec3<f16> */
+ // vector<float16_t> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load &
+ // 0xFFFF));
+ // /* The high 8 bits of first uint is the y element of vec3<f16> */
+ // float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ // Loading code convert it to vec3<f16>:
+ // vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1])
+ std::string ubo_load = UniqueIdentifier("ubo_load");
+ std::string ubo_load_xz = UniqueIdentifier(ubo_load + "_xz");
+ std::string ubo_load_y = UniqueIdentifier(ubo_load + "_y");
+ {
+ auto pre = line();
+ // Load the 8 bytes uint2 with the f16 vector at lower 6 bytes
+ pre << "uint2 " << ubo_load << " = ";
+ if (!load_vec2_u32_to(pre)) {
+ return false;
+ }
+ pre << ";";
+ }
+ {
+ auto pre = line();
+ pre << "vector<float16_t, 2> " << ubo_load_xz
+ << " = vector<float16_t, 2>(f16tof32(" << ubo_load << " & 0xFFFF));";
+ }
+ {
+ auto pre = line();
+ pre << "float16_t " << ubo_load_y << " = f16tof32(" << ubo_load
+ << "[0] >> 16);";
+ }
+ out << "vector<float16_t, 3>(" << ubo_load_xz << "[0], " << ubo_load_y << ", "
+ << ubo_load_xz << "[1])";
+ return true;
+ };
+ auto load_vec4_f16 = [&] {
+ // vec4<f16> is aligned to 8 bytes
+ // Preclude code load the vec4<f16> data as uint2 and convert its elements to
+ // float16_t:
+ // uint2 ubo_load = buffer[id0].xy;
+ // /* The low 8 bits of two uint are the x and z elements of vec4<f16> */
+ // vector<float16_t> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load &
+ // 0xFFFF));
+ // /* The high 8 bits of two uint are the y and w elements of vec4<f16> */
+ // vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >>
+ // 16));
+ // Loading code convert it to vec4<f16>:
+ // vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1],
+ // ubo_load_yw[1])
+ std::string ubo_load = UniqueIdentifier("ubo_load");
+ std::string ubo_load_xz = UniqueIdentifier(ubo_load + "_xz");
+ std::string ubo_load_yw = UniqueIdentifier(ubo_load + "_yw");
+ {
+ auto pre = line();
+ // Load the 8 bytes f16 vector as an uint2
+ pre << "uint2 " << ubo_load << " = ";
+ if (!load_vec2_u32_to(pre)) {
+ return false;
+ }
+ pre << ";";
+ }
+ {
+ auto pre = line();
+ pre << "vector<float16_t, 2> " << ubo_load_xz
+ << " = vector<float16_t, 2>(f16tof32(" << ubo_load << " & 0xFFFF));";
+ }
+ {
+ auto pre = line();
+ pre << "vector<float16_t, 2> " << ubo_load_yw
+ << " = vector<float16_t, 2>(f16tof32(" << ubo_load << " >> 16));";
+ }
+ out << "vector<float16_t, 4>(" << ubo_load_xz << "[0], " << ubo_load_yw << "[0], "
+ << ubo_load_xz << "[1], " << ubo_load_yw << "[1])";
+ return true;
+ };
switch (intrinsic->type) {
case DataType::kU32:
- return load_scalar();
+ return load_u32();
case DataType::kF32:
- return cast("asfloat", load_scalar);
+ return cast("asfloat", load_u32);
case DataType::kI32:
- return cast("asint", load_scalar);
+ return cast("asint", load_u32);
+ case DataType::kF16:
+ return load_scalar_f16();
case DataType::kVec2U32:
- return load_vec2();
+ return load_vec2_u32();
case DataType::kVec2F32:
- return cast("asfloat", load_vec2);
+ return cast("asfloat", load_vec2_u32);
case DataType::kVec2I32:
- return cast("asint", load_vec2);
+ return cast("asint", load_vec2_u32);
+ case DataType::kVec2F16:
+ return load_vec2_f16();
case DataType::kVec3U32:
- return load_vec3();
+ return load_vec3_u32();
case DataType::kVec3F32:
- return cast("asfloat", load_vec3);
+ return cast("asfloat", load_vec3_u32);
case DataType::kVec3I32:
- return cast("asint", load_vec3);
+ return cast("asint", load_vec3_u32);
+ case DataType::kVec3F16:
+ return load_vec3_f16();
case DataType::kVec4U32:
- return load_vec4();
+ return load_vec4_u32();
case DataType::kVec4F32:
- return cast("asfloat", load_vec4);
+ return cast("asfloat", load_vec4_u32);
case DataType::kVec4I32:
- return cast("asint", load_vec4);
+ return cast("asint", load_vec4_u32);
+ case DataType::kVec4F16:
+ return load_vec4_f16();
}
TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
@@ -1257,6 +1421,20 @@
}
return true;
};
+ // Templated load used for f16 types, requires SM6.2 or higher and DXC
+ // Used by loading f16 types, e.g. for f16 type, set type parameter to "float16_t"
+ // to emit `buffer.Load<float16_t>(offset)`.
+ auto templated_load = [&](const char* type) {
+ if (!EmitExpression(out, args[0])) { // buffer
+ return false;
+ }
+ out << ".Load<" << type << ">"; // templated load
+ ScopedParen sp(out);
+ if (!EmitExpression(out, args[1])) { // offset
+ return false;
+ }
+ return true;
+ };
switch (intrinsic->type) {
case DataType::kU32:
return load(nullptr, 1);
@@ -1264,24 +1442,32 @@
return load("asfloat", 1);
case DataType::kI32:
return load("asint", 1);
+ case DataType::kF16:
+ return templated_load("float16_t");
case DataType::kVec2U32:
return load(nullptr, 2);
case DataType::kVec2F32:
return load("asfloat", 2);
case DataType::kVec2I32:
return load("asint", 2);
+ case DataType::kVec2F16:
+ return templated_load("vector<float16_t, 2> ");
case DataType::kVec3U32:
return load(nullptr, 3);
case DataType::kVec3F32:
return load("asfloat", 3);
case DataType::kVec3I32:
return load("asint", 3);
+ case DataType::kVec3F16:
+ return templated_load("vector<float16_t, 3> ");
case DataType::kVec4U32:
return load(nullptr, 4);
case DataType::kVec4F32:
return load("asfloat", 4);
case DataType::kVec4I32:
return load("asint", 4);
+ case DataType::kVec4F16:
+ return templated_load("vector<float16_t, 4> ");
}
TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
@@ -1309,6 +1495,24 @@
}
return true;
};
+ // Templated stored used for f16 types, requires SM6.2 or higher and DXC
+ // Used by storing f16 types, e.g. for f16 type, set type parameter to "float16_t"
+ // to emit `buffer.Store<float16_t>(offset)`.
+ auto templated_store = [&](const char* type) {
+ if (!EmitExpression(out, args[0])) { // buffer
+ return false;
+ }
+ out << ".Store<" << type << ">"; // templated store
+ ScopedParen sp1(out);
+ if (!EmitExpression(out, args[1])) { // offset
+ return false;
+ }
+ out << ", ";
+ if (!EmitExpression(out, args[2])) { // value
+ return false;
+ }
+ return true;
+ };
switch (intrinsic->type) {
case DataType::kU32:
return store(1);
@@ -1316,24 +1520,32 @@
return store(1);
case DataType::kI32:
return store(1);
+ case DataType::kF16:
+ return templated_store("float16_t");
case DataType::kVec2U32:
return store(2);
case DataType::kVec2F32:
return store(2);
case DataType::kVec2I32:
return store(2);
+ case DataType::kVec2F16:
+ return templated_store("vector<float16_t, 2> ");
case DataType::kVec3U32:
return store(3);
case DataType::kVec3F32:
return store(3);
case DataType::kVec3I32:
return store(3);
+ case DataType::kVec3F16:
+ return templated_store("vector<float16_t, 3> ");
case DataType::kVec4U32:
return store(4);
case DataType::kVec4F32:
return store(4);
case DataType::kVec4I32:
return store(4);
+ case DataType::kVec4F16:
+ return templated_store("vector<float16_t, 4> ");
}
TINT_UNREACHABLE(Writer, diagnostics_)
<< "unsupported DecomposeMemoryAccess::Intrinsic::DataType: "
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
index 3e9b169..8b5fe07 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
@@ -388,12 +388,12 @@
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct modf_result {
+ EXPECT_EQ(gen.result(), R"(struct modf_result_f32 {
float fract;
float whole;
};
-modf_result tint_modf(float param_0) {
- modf_result result;
+modf_result_f32 tint_modf(float param_0) {
+ modf_result_f32 result;
result.fract = modf(param_0, result.whole);
return result;
}
@@ -401,7 +401,7 @@
[numthreads(1, 1, 1)]
void test_function() {
const float f = 1.5f;
- const modf_result v = tint_modf(f);
+ const modf_result_f32 v = tint_modf(f);
return;
}
)");
@@ -442,12 +442,12 @@
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct modf_result_vec3 {
+ EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f32 {
float3 fract;
float3 whole;
};
-modf_result_vec3 tint_modf(float3 param_0) {
- modf_result_vec3 result;
+modf_result_vec3_f32 tint_modf(float3 param_0) {
+ modf_result_vec3_f32 result;
result.fract = modf(param_0, result.whole);
return result;
}
@@ -455,7 +455,7 @@
[numthreads(1, 1, 1)]
void test_function() {
const float3 f = float3(1.5f, 2.5f, 3.5f);
- const modf_result_vec3 v = tint_modf(f);
+ const modf_result_vec3_f32 v = tint_modf(f);
return;
}
)");
@@ -495,13 +495,13 @@
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct modf_result {
+ EXPECT_EQ(gen.result(), R"(struct modf_result_f32 {
float fract;
float whole;
};
[numthreads(1, 1, 1)]
void test_function() {
- const modf_result v = {0.5f, 1.0f};
+ const modf_result_f32 v = {0.5f, 1.0f};
return;
}
)");
@@ -533,13 +533,13 @@
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct modf_result_vec3 {
+ EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f32 {
float3 fract;
float3 whole;
};
[numthreads(1, 1, 1)]
void test_function() {
- const modf_result_vec3 v = {(0.5f).xxx, float3(1.0f, 2.0f, 3.0f)};
+ const modf_result_vec3_f32 v = {(0.5f).xxx, float3(1.0f, 2.0f, 3.0f)};
return;
}
)");
@@ -572,56 +572,57 @@
Decl(Var("v", Call("modf", vec3<f32>(1.5_f, 2.5_f, 3.5_f)))),
// Now assign 'v' again with another modf call.
// This requires generating a temporary variable for the struct initializer.
- Assign("v", Call("modf", vec3<f32>(4.5_f, 5.5_f, 6.5_f))));
+ Assign("v", Call("modf", vec3<f32>(4.5_a, 5.5_a, 6.5_a))));
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct modf_result_vec3 {
+ EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f32 {
float3 fract;
float3 whole;
};
[numthreads(1, 1, 1)]
void test_function() {
- modf_result_vec3 v = {(0.5f).xxx, float3(1.0f, 2.0f, 3.0f)};
- const modf_result_vec3 c = {(0.5f).xxx, float3(4.0f, 5.0f, 6.0f)};
+ modf_result_vec3_f32 v = {(0.5f).xxx, float3(1.0f, 2.0f, 3.0f)};
+ const modf_result_vec3_f32 c = {(0.5f).xxx, float3(4.0f, 5.0f, 6.0f)};
v = c;
return;
}
)");
}
-TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Scalar_f32) {
- auto* call = Call("frexp", 1_f);
- WrapInFunction(CallStmt(call));
+TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Frexp_Scalar_f32) {
+ WrapInFunction(Var("f", Expr(1_f)), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct frexp_result {
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_f32 {
float fract;
int exp;
};
-frexp_result tint_frexp(float param_0) {
+frexp_result_f32 tint_frexp(float param_0) {
float exp;
float fract = frexp(param_0, exp);
- frexp_result result = {fract, int(exp)};
+ frexp_result_f32 result = {fract, int(exp)};
return result;
}
[numthreads(1, 1, 1)]
void test_function() {
- tint_frexp(1.0f);
+ float f = 1.0f;
+ frexp_result_f32 v = tint_frexp(f);
return;
}
)");
}
-TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Scalar_f16) {
+TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Frexp_Scalar_f16) {
Enable(ast::Extension::kF16);
- auto* call = Call("frexp", 1_h);
- WrapInFunction(CallStmt(call));
+ WrapInFunction(Var("f", Expr(1_h)), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -639,43 +640,45 @@
[numthreads(1, 1, 1)]
void test_function() {
- tint_frexp(float16_t(1.0h));
+ float16_t f = float16_t(1.0h);
+ frexp_result_f16 v = tint_frexp(f);
return;
}
)");
}
-TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Vector_f32) {
- auto* call = Call("frexp", vec3<f32>());
- WrapInFunction(CallStmt(call));
+TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f32) {
+ WrapInFunction(Var("f", Expr(vec3<f32>())), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3 {
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f32 {
float3 fract;
int3 exp;
};
-frexp_result_vec3 tint_frexp(float3 param_0) {
+frexp_result_vec3_f32 tint_frexp(float3 param_0) {
float3 exp;
float3 fract = frexp(param_0, exp);
- frexp_result_vec3 result = {fract, int3(exp)};
+ frexp_result_vec3_f32 result = {fract, int3(exp)};
return result;
}
[numthreads(1, 1, 1)]
void test_function() {
- tint_frexp((0.0f).xxx);
+ float3 f = (0.0f).xxx;
+ frexp_result_vec3_f32 v = tint_frexp(f);
return;
}
)");
}
-TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Vector_f16) {
+TEST_F(HlslGeneratorImplTest_Builtin, Runtime_Frexp_Vector_f16) {
Enable(ast::Extension::kF16);
- auto* call = Call("frexp", vec3<f16>());
- WrapInFunction(CallStmt(call));
+ WrapInFunction(Var("f", Expr(vec3<f16>())), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -693,7 +696,110 @@
[numthreads(1, 1, 1)]
void test_function() {
- tint_frexp((float16_t(0.0h)).xxx);
+ vector<float16_t, 3> f = (float16_t(0.0h)).xxx;
+ frexp_result_vec3_f16 v = tint_frexp(f);
+ return;
+}
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Builtin, Const_Frexp_Scalar_f32) {
+ WrapInFunction(Decl(Let("v", Call("frexp", 1_f))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_f32 {
+ float fract;
+ int exp;
+};
+[numthreads(1, 1, 1)]
+void test_function() {
+ const frexp_result_f32 v = {0.5f, 1};
+ return;
+}
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Builtin, Const_Frexp_Scalar_f16) {
+ Enable(ast::Extension::kF16);
+
+ WrapInFunction(Decl(Let("v", Call("frexp", 1_h))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_f16 {
+ float16_t fract;
+ int exp;
+};
+[numthreads(1, 1, 1)]
+void test_function() {
+ const frexp_result_f16 v = {float16_t(0.5h), 1};
+ return;
+}
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f32) {
+ WrapInFunction(Decl(Let("v", Call("frexp", vec3<f32>()))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f32 {
+ float3 fract;
+ int3 exp;
+};
+[numthreads(1, 1, 1)]
+void test_function() {
+ const frexp_result_vec3_f32 v = (frexp_result_vec3_f32)0;
+ return;
+}
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Builtin, Const_Frexp_Vector_f16) {
+ Enable(ast::Extension::kF16);
+
+ WrapInFunction(Decl(Let("v", Call("frexp", vec3<f16>()))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f16 {
+ vector<float16_t, 3> fract;
+ int3 exp;
+};
+[numthreads(1, 1, 1)]
+void test_function() {
+ const frexp_result_vec3_f16 v = (frexp_result_vec3_f16)0;
+ return;
+}
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Builtin, NonInitializer_Frexp_Vector_f32) {
+ WrapInFunction(
+ // Declare a variable with the result of a frexp call.
+ // This is required to infer the 'var' type.
+ Decl(Var("v", Call("frexp", vec3<f32>(1.5_f, 2.5_f, 3.5_f)))),
+ // Now assign 'v' again with another frexp call.
+ // This requires generating a temporary variable for the struct initializer.
+ Assign("v", Call("frexp", vec3<f32>(4.5_a, 5.5_a, 6.5_a))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f32 {
+ float3 fract;
+ int3 exp;
+};
+[numthreads(1, 1, 1)]
+void test_function() {
+ frexp_result_vec3_f32 v = {float3(0.75f, 0.625f, 0.875f), int3(1, 2, 2)};
+ const frexp_result_vec3_f32 c = {float3(0.5625f, 0.6875f, 0.8125f), (3).xxx};
+ v = c;
return;
}
)");
@@ -701,25 +807,20 @@
// TODO(crbug.com/tint/1757): Remove once deprecation period for `frexp().sig` is over
TEST_F(HlslGeneratorImplTest_Builtin, Frexp_Sig_Deprecation) {
- WrapInFunction(MemberAccessor(Call("frexp", 1_f), "sig"));
+ WrapInFunction(Var("v", Call("frexp", 1_f)), //
+ MemberAccessor("v", "sig"));
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_EQ(gen.result(), R"(struct frexp_result {
+ EXPECT_EQ(gen.result(), R"(struct frexp_result_f32 {
float fract;
int exp;
};
-frexp_result tint_frexp(float param_0) {
- float exp;
- float fract = frexp(param_0, exp);
- frexp_result result = {fract, int(exp)};
- return result;
-}
-
[numthreads(1, 1, 1)]
void test_function() {
- const float tint_symbol = tint_frexp(1.0f).fract;
+ frexp_result_f32 v = {0.5f, 1};
+ const float tint_symbol = v.fract;
return;
}
)");
diff --git a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
index 1fbef9b..b3440b8 100644
--- a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -34,6 +34,9 @@
inline const ast::Type* ty_f32(const ProgramBuilder::TypesBuilder& ty) {
return ty.f32();
}
+inline const ast::Type* ty_f16(const ProgramBuilder::TypesBuilder& ty) {
+ return ty.f16();
+}
template <typename T>
inline const ast::Type* ty_vec2(const ProgramBuilder::TypesBuilder& ty) {
return ty.vec2<T>();
@@ -94,6 +97,14 @@
b.Group(1_a), b.Binding(0_a));
}
+ void SetupUniformBuffer(utils::VectorRef<const ast::StructMember*> members) {
+ ProgramBuilder& b = *this;
+ auto* s = b.Structure("Data", members);
+
+ b.GlobalVar("data", b.ty.Of(s), ast::AddressSpace::kUniform, ast::Access::kUndefined,
+ b.Group(1_a), b.Binding(1_a));
+ }
+
void SetupFunction(utils::VectorRef<const ast::Statement*> statements) {
ProgramBuilder& b = *this;
utils::Vector attrs{
@@ -144,18 +155,21 @@
return out;
}
-using HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad =
+using HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad_ConstantOffset =
HlslGeneratorImplTest_MemberAccessorWithParam<TypeCase>;
-TEST_P(HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad, Test) {
+
+TEST_P(HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad_ConstantOffset, Test) {
// struct Data {
- // a : i32;
- // b : <type>;
+ // a : i32,
+ // b : <type>,
// };
// var<storage> data : Data;
// data.b;
auto p = GetParam();
+ Enable(ast::Extension::kF16);
+
SetupStorageBuffer(utils::Vector{
Member("a", ty.i32()),
Member("b", p.member_type(ty)),
@@ -173,60 +187,813 @@
INSTANTIATE_TEST_SUITE_P(
HlslGeneratorImplTest_MemberAccessor,
- HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad,
+ HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad_ConstantOffset,
+ testing::Values(TypeCase{ty_u32, "data.Load(4u)"},
+ TypeCase{ty_f32, "asfloat(data.Load(4u))"},
+ TypeCase{ty_i32, "asint(data.Load(4u))"},
+ TypeCase{ty_f16, "data.Load<float16_t>(4u)"},
+ TypeCase{ty_vec2<u32>, "data.Load2(8u)"},
+ TypeCase{ty_vec2<f32>, "asfloat(data.Load2(8u))"},
+ TypeCase{ty_vec2<i32>, "asint(data.Load2(8u))"},
+ TypeCase{ty_vec2<f16>, "data.Load<vector<float16_t, 2> >(4u)"},
+ TypeCase{ty_vec3<u32>, "data.Load3(16u)"},
+ TypeCase{ty_vec3<f32>, "asfloat(data.Load3(16u))"},
+ TypeCase{ty_vec3<i32>, "asint(data.Load3(16u))"},
+ TypeCase{ty_vec3<f16>, "data.Load<vector<float16_t, 3> >(8u)"},
+ TypeCase{ty_vec4<u32>, "data.Load4(16u)"},
+ TypeCase{ty_vec4<f32>, "asfloat(data.Load4(16u))"},
+ TypeCase{ty_vec4<i32>, "asint(data.Load4(16u))"},
+ TypeCase{ty_vec4<f16>, "data.Load<vector<float16_t, 4> >(8u)"},
+ TypeCase{ty_mat2x2<f32>,
+ "return float2x2(asfloat(buffer.Load2((offset + 0u))), "
+ "asfloat(buffer.Load2((offset + 8u))));"},
+ TypeCase{ty_mat2x3<f32>,
+ "return float2x3(asfloat(buffer.Load3((offset + 0u))), "
+ "asfloat(buffer.Load3((offset + 16u))));"},
+ TypeCase{ty_mat2x4<f32>,
+ "return float2x4(asfloat(buffer.Load4((offset + 0u))), "
+ "asfloat(buffer.Load4((offset + 16u))));"},
+ TypeCase{ty_mat3x2<f32>,
+ "return float3x2(asfloat(buffer.Load2((offset + 0u))), "
+ "asfloat(buffer.Load2((offset + 8u))), "
+ "asfloat(buffer.Load2((offset + 16u))));"},
+ TypeCase{ty_mat3x3<f32>,
+ "return float3x3(asfloat(buffer.Load3((offset + 0u))), "
+ "asfloat(buffer.Load3((offset + 16u))), "
+ "asfloat(buffer.Load3((offset + 32u))));"},
+ TypeCase{ty_mat3x4<f32>,
+ "return float3x4(asfloat(buffer.Load4((offset + 0u))), "
+ "asfloat(buffer.Load4((offset + 16u))), "
+ "asfloat(buffer.Load4((offset + 32u))));"},
+ TypeCase{ty_mat4x2<f32>,
+ "return float4x2(asfloat(buffer.Load2((offset + 0u))), "
+ "asfloat(buffer.Load2((offset + 8u))), "
+ "asfloat(buffer.Load2((offset + 16u))), "
+ "asfloat(buffer.Load2((offset + 24u))));"},
+ TypeCase{ty_mat4x3<f32>,
+ "return float4x3(asfloat(buffer.Load3((offset + 0u))), "
+ "asfloat(buffer.Load3((offset + 16u))), "
+ "asfloat(buffer.Load3((offset + 32u))), "
+ "asfloat(buffer.Load3((offset + 48u))));"},
+ TypeCase{ty_mat4x4<f32>,
+ "return float4x4(asfloat(buffer.Load4((offset + 0u))), "
+ "asfloat(buffer.Load4((offset + 16u))), "
+ "asfloat(buffer.Load4((offset + 32u))), "
+ "asfloat(buffer.Load4((offset + 48u))));"},
+ TypeCase{ty_mat2x2<f16>,
+ "return matrix<float16_t, 2, 2>("
+ "buffer.Load<vector<float16_t, 2> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 4u)));"},
+ TypeCase{ty_mat2x3<f16>,
+ "return matrix<float16_t, 2, 3>("
+ "buffer.Load<vector<float16_t, 3> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 8u)));"},
+ TypeCase{ty_mat2x4<f16>,
+ "return matrix<float16_t, 2, 4>("
+ "buffer.Load<vector<float16_t, 4> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 8u)));"},
+ TypeCase{ty_mat3x2<f16>,
+ "return matrix<float16_t, 3, 2>("
+ "buffer.Load<vector<float16_t, 2> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 4u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 8u)));"},
+ TypeCase{ty_mat3x3<f16>,
+ "return matrix<float16_t, 3, 3>("
+ "buffer.Load<vector<float16_t, 3> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 16u)));"},
+ TypeCase{ty_mat3x4<f16>,
+ "return matrix<float16_t, 3, 4>("
+ "buffer.Load<vector<float16_t, 4> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 16u)));"},
+ TypeCase{ty_mat4x2<f16>,
+ "return matrix<float16_t, 4, 2>("
+ "buffer.Load<vector<float16_t, 2> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 4u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 12u)));"},
+ TypeCase{ty_mat4x3<f16>,
+ "return matrix<float16_t, 4, 3>("
+ "buffer.Load<vector<float16_t, 3> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 16u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 24u)));"},
+ TypeCase{ty_mat4x4<f16>,
+ "return matrix<float16_t, 4, 4>("
+ "buffer.Load<vector<float16_t, 4> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 16u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 24u)));"}));
+
+using HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad_DynamicOffset =
+ HlslGeneratorImplTest_MemberAccessorWithParam<TypeCase>;
+
+TEST_P(HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad_DynamicOffset, Test) {
+ // struct Inner {
+ // a : i32,
+ // b : <type>,
+ // c : vec4<i32>,
+ // };
+ // struct Data {
+ // arr : array<Inner, 4i>,
+ // }
+ // var<storage> data : Data;
+ // data.arr[i].b;
+
+ auto p = GetParam();
+
+ Enable(ast::Extension::kF16);
+
+ auto* inner = Structure("Inner", utils::Vector{
+ Member("a", ty.i32()),
+ Member("b", p.member_type(ty)),
+ Member("c", ty.vec4(ty.i32())),
+ });
+
+ SetupStorageBuffer(utils::Vector{
+ Member("arr", ty.array(ty.Of(inner), 4_i)),
+ });
+
+ auto* i = Var("i", Expr(2_i));
+
+ SetupFunction(utils::Vector{
+ Decl(i),
+ Decl(Var("x", MemberAccessor(IndexAccessor(MemberAccessor("data", "arr"), i), "b"))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ HlslGeneratorImplTest_MemberAccessor,
+ HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad_DynamicOffset,
testing::Values(
- TypeCase{ty_u32, "data.Load(4u)"},
- TypeCase{ty_f32, "asfloat(data.Load(4u))"},
- TypeCase{ty_i32, "asint(data.Load(4u))"},
- TypeCase{ty_vec2<u32>, "data.Load2(8u)"},
- TypeCase{ty_vec2<f32>, "asfloat(data.Load2(8u))"},
- TypeCase{ty_vec2<i32>, "asint(data.Load2(8u))"},
- TypeCase{ty_vec3<u32>, "data.Load3(16u)"},
- TypeCase{ty_vec3<f32>, "asfloat(data.Load3(16u))"},
- TypeCase{ty_vec3<i32>, "asint(data.Load3(16u))"},
- TypeCase{ty_vec4<u32>, "data.Load4(16u)"},
- TypeCase{ty_vec4<f32>, "asfloat(data.Load4(16u))"},
- TypeCase{ty_vec4<i32>, "asint(data.Load4(16u))"},
- TypeCase{
- ty_mat2x2<f32>,
- R"(return float2x2(asfloat(buffer.Load2((offset + 0u))), asfloat(buffer.Load2((offset + 8u))));)"},
- TypeCase{
- ty_mat2x3<f32>,
- R"(return float2x3(asfloat(buffer.Load3((offset + 0u))), asfloat(buffer.Load3((offset + 16u))));)"},
- TypeCase{
- ty_mat2x4<f32>,
- R"(return float2x4(asfloat(buffer.Load4((offset + 0u))), asfloat(buffer.Load4((offset + 16u))));)"},
- TypeCase{
- ty_mat3x2<f32>,
- R"(return float3x2(asfloat(buffer.Load2((offset + 0u))), asfloat(buffer.Load2((offset + 8u))), asfloat(buffer.Load2((offset + 16u))));)"},
- TypeCase{
- ty_mat3x3<f32>,
- R"(return float3x3(asfloat(buffer.Load3((offset + 0u))), asfloat(buffer.Load3((offset + 16u))), asfloat(buffer.Load3((offset + 32u))));)"},
- TypeCase{
- ty_mat3x4<f32>,
- R"(return float3x4(asfloat(buffer.Load4((offset + 0u))), asfloat(buffer.Load4((offset + 16u))), asfloat(buffer.Load4((offset + 32u))));)"},
- TypeCase{
- ty_mat4x2<f32>,
- R"(return float4x2(asfloat(buffer.Load2((offset + 0u))), asfloat(buffer.Load2((offset + 8u))), asfloat(buffer.Load2((offset + 16u))), asfloat(buffer.Load2((offset + 24u))));)"},
- TypeCase{
- ty_mat4x3<f32>,
- R"(return float4x3(asfloat(buffer.Load3((offset + 0u))), asfloat(buffer.Load3((offset + 16u))), asfloat(buffer.Load3((offset + 32u))), asfloat(buffer.Load3((offset + 48u))));)"},
- TypeCase{
- ty_mat4x4<f32>,
- R"(return float4x4(asfloat(buffer.Load4((offset + 0u))), asfloat(buffer.Load4((offset + 16u))), asfloat(buffer.Load4((offset + 32u))), asfloat(buffer.Load4((offset + 48u))));)"}));
+ TypeCase{ty_u32, "data.Load(((32u * uint(i)) + 4u))"},
+ TypeCase{ty_f32, "asfloat(data.Load(((32u * uint(i)) + 4u)))"},
+ TypeCase{ty_i32, "asint(data.Load(((32u * uint(i)) + 4u)))"},
+ TypeCase{ty_f16, "data.Load<float16_t>(((32u * uint(i)) + 4u))"},
+ TypeCase{ty_vec2<u32>, "data.Load2(((32u * uint(i)) + 8u))"},
+ TypeCase{ty_vec2<f32>, "asfloat(data.Load2(((32u * uint(i)) + 8u)))"},
+ TypeCase{ty_vec2<i32>, "asint(data.Load2(((32u * uint(i)) + 8u)))"},
+ TypeCase{ty_vec2<f16>, "data.Load<vector<float16_t, 2> >(((32u * uint(i)) + 4u))"},
+ TypeCase{ty_vec3<u32>, "data.Load3(((48u * uint(i)) + 16u))"},
+ TypeCase{ty_vec3<f32>, "asfloat(data.Load3(((48u * uint(i)) + 16u)))"},
+ TypeCase{ty_vec3<i32>, "asint(data.Load3(((48u * uint(i)) + 16u)))"},
+ TypeCase{ty_vec3<f16>, "data.Load<vector<float16_t, 3> >(((32u * uint(i)) + 8u))"},
+ TypeCase{ty_vec4<u32>, "data.Load4(((48u * uint(i)) + 16u))"},
+ TypeCase{ty_vec4<f32>, "asfloat(data.Load4(((48u * uint(i)) + 16u)))"},
+ TypeCase{ty_vec4<i32>, "asint(data.Load4(((48u * uint(i)) + 16u)))"},
+ TypeCase{ty_vec4<f16>, "data.Load<vector<float16_t, 4> >(((32u * uint(i)) + 8u))"},
+ TypeCase{ty_mat2x2<f32>,
+ "return float2x2(asfloat(buffer.Load2((offset + 0u))), "
+ "asfloat(buffer.Load2((offset + 8u))));"},
+ TypeCase{ty_mat2x3<f32>,
+ "return float2x3(asfloat(buffer.Load3((offset + 0u))), "
+ "asfloat(buffer.Load3((offset + 16u))));"},
+ TypeCase{ty_mat2x4<f32>,
+ "return float2x4(asfloat(buffer.Load4((offset + 0u))), "
+ "asfloat(buffer.Load4((offset + 16u))));"},
+ TypeCase{ty_mat3x2<f32>,
+ "return float3x2(asfloat(buffer.Load2((offset + 0u))), "
+ "asfloat(buffer.Load2((offset + 8u))), "
+ "asfloat(buffer.Load2((offset + 16u))));"},
+ TypeCase{ty_mat3x3<f32>,
+ "return float3x3(asfloat(buffer.Load3((offset + 0u))), "
+ "asfloat(buffer.Load3((offset + 16u))), "
+ "asfloat(buffer.Load3((offset + 32u))));"},
+ TypeCase{ty_mat3x4<f32>,
+ "return float3x4(asfloat(buffer.Load4((offset + 0u))), "
+ "asfloat(buffer.Load4((offset + 16u))), "
+ "asfloat(buffer.Load4((offset + 32u))));"},
+ TypeCase{ty_mat4x2<f32>,
+ "return float4x2(asfloat(buffer.Load2((offset + 0u))), "
+ "asfloat(buffer.Load2((offset + 8u))), "
+ "asfloat(buffer.Load2((offset + 16u))), "
+ "asfloat(buffer.Load2((offset + 24u))));"},
+ TypeCase{ty_mat4x3<f32>,
+ "return float4x3(asfloat(buffer.Load3((offset + 0u))), "
+ "asfloat(buffer.Load3((offset + 16u))), "
+ "asfloat(buffer.Load3((offset + 32u))), "
+ "asfloat(buffer.Load3((offset + 48u))));"},
+ TypeCase{ty_mat4x4<f32>,
+ "return float4x4(asfloat(buffer.Load4((offset + 0u))), "
+ "asfloat(buffer.Load4((offset + 16u))), "
+ "asfloat(buffer.Load4((offset + 32u))), "
+ "asfloat(buffer.Load4((offset + 48u))));"},
+ TypeCase{ty_mat2x2<f16>,
+ "return matrix<float16_t, 2, 2>("
+ "buffer.Load<vector<float16_t, 2> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 4u)));"},
+ TypeCase{ty_mat2x3<f16>,
+ "return matrix<float16_t, 2, 3>("
+ "buffer.Load<vector<float16_t, 3> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 8u)));"},
+ TypeCase{ty_mat2x4<f16>,
+ "return matrix<float16_t, 2, 4>("
+ "buffer.Load<vector<float16_t, 4> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 8u)));"},
+ TypeCase{ty_mat3x2<f16>,
+ "return matrix<float16_t, 3, 2>("
+ "buffer.Load<vector<float16_t, 2> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 4u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 8u)));"},
+ TypeCase{ty_mat3x3<f16>,
+ "return matrix<float16_t, 3, 3>("
+ "buffer.Load<vector<float16_t, 3> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 16u)));"},
+ TypeCase{ty_mat3x4<f16>,
+ "return matrix<float16_t, 3, 4>("
+ "buffer.Load<vector<float16_t, 4> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 16u)));"},
+ TypeCase{ty_mat4x2<f16>,
+ "return matrix<float16_t, 4, 2>("
+ "buffer.Load<vector<float16_t, 2> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 4u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 2> >((offset + 12u)));"},
+ TypeCase{ty_mat4x3<f16>,
+ "return matrix<float16_t, 4, 3>("
+ "buffer.Load<vector<float16_t, 3> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 16u)), "
+ "buffer.Load<vector<float16_t, 3> >((offset + 24u)));"},
+ TypeCase{ty_mat4x4<f16>,
+ "return matrix<float16_t, 4, 4>("
+ "buffer.Load<vector<float16_t, 4> >((offset + 0u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 8u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 16u)), "
+ "buffer.Load<vector<float16_t, 4> >((offset + 24u)));"}));
+
+using HlslGeneratorImplTest_MemberAccessor_UniformBufferLoad_ConstantOffset =
+ HlslGeneratorImplTest_MemberAccessorWithParam<TypeCase>;
+TEST_P(HlslGeneratorImplTest_MemberAccessor_UniformBufferLoad_ConstantOffset, Test) {
+ // struct Data {
+ // a : i32,
+ // b : <type>,
+ // };
+ // var<uniform> data : Data;
+ // data.b;
+
+ auto p = GetParam();
+
+ Enable(ast::Extension::kF16);
+
+ SetupUniformBuffer(utils::Vector{
+ Member("a", ty.i32()),
+ Member("b", p.member_type(ty)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", MemberAccessor("data", "b"))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ HlslGeneratorImplTest_MemberAccessor,
+ HlslGeneratorImplTest_MemberAccessor_UniformBufferLoad_ConstantOffset,
+ testing::Values(TypeCase{ty_u32, "uint x = data[0].y;"},
+ TypeCase{ty_f32, "float x = asfloat(data[0].y);"},
+ TypeCase{ty_i32, "int x = asint(data[0].y);"},
+ TypeCase{ty_f16, "float16_t x = float16_t(f16tof32(((data[0].y) & 0xFFFF)));"},
+ TypeCase{ty_vec2<u32>, "uint2 x = data[0].zw;"},
+ TypeCase{ty_vec2<f32>, "float2 x = asfloat(data[0].zw);"},
+ TypeCase{ty_vec2<i32>, "int2 x = asint(data[0].zw);"},
+ TypeCase{ty_vec2<f16>, R"(uint ubo_load = data[0].y;
+ vector<float16_t, 2> x = vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16)));)"},
+ TypeCase{ty_vec3<u32>, "uint3 x = data[1].xyz;"},
+ TypeCase{ty_vec3<f32>, "float3 x = asfloat(data[1].xyz);"},
+ TypeCase{ty_vec3<i32>, "int3 x = asint(data[1].xyz);"},
+ TypeCase{ty_vec3<f16>, R"(uint2 ubo_load = data[0].zw;
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ vector<float16_t, 3> x = vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]);)"},
+ TypeCase{ty_vec4<u32>, "uint4 x = data[1];"},
+ TypeCase{ty_vec4<f32>, "float4 x = asfloat(data[1]);"},
+ TypeCase{ty_vec4<i32>, "int4 x = asint(data[1]);"},
+ TypeCase{ty_vec4<f16>,
+ R"(uint2 ubo_load = data[0].zw;
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ vector<float16_t, 4> x = vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]);)"},
+ TypeCase{ty_mat2x2<f32>, R"(float2x2 tint_symbol(uint4 buffer[2], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load = buffer[scalar_offset / 4];
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+ return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+})"},
+ TypeCase{ty_mat2x3<f32>, R"(float2x3 tint_symbol(uint4 buffer[3], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ return float2x3(asfloat(buffer[scalar_offset / 4].xyz), asfloat(buffer[scalar_offset_1 / 4].xyz));
+})"},
+ TypeCase{ty_mat2x4<f32>, R"(float2x4 tint_symbol(uint4 buffer[3], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ return float2x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]));
+})"},
+ TypeCase{ty_mat3x2<f32>, R"(float3x2 tint_symbol(uint4 buffer[2], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load = buffer[scalar_offset / 4];
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+ return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+})"},
+ TypeCase{ty_mat3x3<f32>, R"(float3x3 tint_symbol(uint4 buffer[4], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ return float3x3(asfloat(buffer[scalar_offset / 4].xyz), asfloat(buffer[scalar_offset_1 / 4].xyz), asfloat(buffer[scalar_offset_2 / 4].xyz));
+})"},
+ TypeCase{ty_mat3x4<f32>, R"(float3x4 tint_symbol(uint4 buffer[4], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ return float3x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]), asfloat(buffer[scalar_offset_2 / 4]));
+})"},
+ TypeCase{ty_mat4x2<f32>, R"(float4x2 tint_symbol(uint4 buffer[3], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load = buffer[scalar_offset / 4];
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+ const uint scalar_offset_3 = ((offset + 24u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+ return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+})"},
+ TypeCase{ty_mat4x3<f32>, R"(float4x3 tint_symbol(uint4 buffer[5], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ const uint scalar_offset_3 = ((offset + 48u)) / 4;
+ return float4x3(asfloat(buffer[scalar_offset / 4].xyz), asfloat(buffer[scalar_offset_1 / 4].xyz), asfloat(buffer[scalar_offset_2 / 4].xyz), asfloat(buffer[scalar_offset_3 / 4].xyz));
+})"},
+ TypeCase{ty_mat4x4<f32>, R"(float4x4 tint_symbol(uint4 buffer[5], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ const uint scalar_offset_3 = ((offset + 48u)) / 4;
+ return float4x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]), asfloat(buffer[scalar_offset_2 / 4]), asfloat(buffer[scalar_offset_3 / 4]));
+})"},
+ TypeCase{ty_mat2x2<f16>,
+ R"(matrix<float16_t, 2, 2> tint_symbol(uint4 buffer[1], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint ubo_load = buffer[scalar_offset / 4][scalar_offset % 4];
+ const uint scalar_offset_1 = ((offset + 4u)) / 4;
+ uint ubo_load_1 = buffer[scalar_offset_1 / 4][scalar_offset_1 % 4];
+ return matrix<float16_t, 2, 2>(vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_1 & 0xFFFF)), float16_t(f16tof32(ubo_load_1 >> 16))));
+})"},
+ TypeCase{ty_mat2x3<f16>,
+ R"(matrix<float16_t, 2, 3> tint_symbol(uint4 buffer[2], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ float16_t ubo_load_2_y = f16tof32(ubo_load_2[0] >> 16);
+ return matrix<float16_t, 2, 3>(vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]), vector<float16_t, 3>(ubo_load_2_xz[0], ubo_load_2_y, ubo_load_2_xz[1]));
+})"},
+ TypeCase{ty_mat2x4<f16>,
+ R"(matrix<float16_t, 2, 4> tint_symbol(uint4 buffer[2], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_2_yw = vector<float16_t, 2>(f16tof32(ubo_load_2 >> 16));
+ return matrix<float16_t, 2, 4>(vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]), vector<float16_t, 4>(ubo_load_2_xz[0], ubo_load_2_yw[0], ubo_load_2_xz[1], ubo_load_2_yw[1]));
+})"},
+ TypeCase{ty_mat3x2<f16>,
+ R"(matrix<float16_t, 3, 2> tint_symbol(uint4 buffer[1], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint ubo_load = buffer[scalar_offset / 4][scalar_offset % 4];
+ const uint scalar_offset_1 = ((offset + 4u)) / 4;
+ uint ubo_load_1 = buffer[scalar_offset_1 / 4][scalar_offset_1 % 4];
+ const uint scalar_offset_2 = ((offset + 8u)) / 4;
+ uint ubo_load_2 = buffer[scalar_offset_2 / 4][scalar_offset_2 % 4];
+ return matrix<float16_t, 3, 2>(vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_1 & 0xFFFF)), float16_t(f16tof32(ubo_load_1 >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_2 & 0xFFFF)), float16_t(f16tof32(ubo_load_2 >> 16))));
+})"},
+ TypeCase{ty_mat3x3<f16>,
+ R"(matrix<float16_t, 3, 3> tint_symbol(uint4 buffer[2], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ float16_t ubo_load_2_y = f16tof32(ubo_load_2[0] >> 16);
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ float16_t ubo_load_4_y = f16tof32(ubo_load_4[0] >> 16);
+ return matrix<float16_t, 3, 3>(vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]), vector<float16_t, 3>(ubo_load_2_xz[0], ubo_load_2_y, ubo_load_2_xz[1]), vector<float16_t, 3>(ubo_load_4_xz[0], ubo_load_4_y, ubo_load_4_xz[1]));
+})"},
+ TypeCase{ty_mat3x4<f16>,
+ R"(matrix<float16_t, 3, 4> tint_symbol(uint4 buffer[2], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_2_yw = vector<float16_t, 2>(f16tof32(ubo_load_2 >> 16));
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_4_yw = vector<float16_t, 2>(f16tof32(ubo_load_4 >> 16));
+ return matrix<float16_t, 3, 4>(vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]), vector<float16_t, 4>(ubo_load_2_xz[0], ubo_load_2_yw[0], ubo_load_2_xz[1], ubo_load_2_yw[1]), vector<float16_t, 4>(ubo_load_4_xz[0], ubo_load_4_yw[0], ubo_load_4_xz[1], ubo_load_4_yw[1]));)"},
+ TypeCase{ty_mat4x2<f16>,
+ R"(matrix<float16_t, 4, 2> tint_symbol(uint4 buffer[2], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint ubo_load = buffer[scalar_offset / 4][scalar_offset % 4];
+ const uint scalar_offset_1 = ((offset + 4u)) / 4;
+ uint ubo_load_1 = buffer[scalar_offset_1 / 4][scalar_offset_1 % 4];
+ const uint scalar_offset_2 = ((offset + 8u)) / 4;
+ uint ubo_load_2 = buffer[scalar_offset_2 / 4][scalar_offset_2 % 4];
+ const uint scalar_offset_3 = ((offset + 12u)) / 4;
+ uint ubo_load_3 = buffer[scalar_offset_3 / 4][scalar_offset_3 % 4];
+ return matrix<float16_t, 4, 2>(vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_1 & 0xFFFF)), float16_t(f16tof32(ubo_load_1 >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_2 & 0xFFFF)), float16_t(f16tof32(ubo_load_2 >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_3 & 0xFFFF)), float16_t(f16tof32(ubo_load_3 >> 16))));
+})"},
+ TypeCase{ty_mat4x3<f16>,
+ R"(matrix<float16_t, 4, 3> tint_symbol(uint4 buffer[3], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ float16_t ubo_load_2_y = f16tof32(ubo_load_2[0] >> 16);
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ float16_t ubo_load_4_y = f16tof32(ubo_load_4[0] >> 16);
+ const uint scalar_offset_3 = ((offset + 24u)) / 4;
+ uint4 ubo_load_7 = buffer[scalar_offset_3 / 4];
+ uint2 ubo_load_6 = ((scalar_offset_3 & 2) ? ubo_load_7.zw : ubo_load_7.xy);
+ vector<float16_t, 2> ubo_load_6_xz = vector<float16_t, 2>(f16tof32(ubo_load_6 & 0xFFFF));
+ float16_t ubo_load_6_y = f16tof32(ubo_load_6[0] >> 16);
+ return matrix<float16_t, 4, 3>(vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]), vector<float16_t, 3>(ubo_load_2_xz[0], ubo_load_2_y, ubo_load_2_xz[1]), vector<float16_t, 3>(ubo_load_4_xz[0], ubo_load_4_y, ubo_load_4_xz[1]), vector<float16_t, 3>(ubo_load_6_xz[0], ubo_load_6_y, ubo_load_6_xz[1]));
+})"},
+ TypeCase{ty_mat4x4<f16>,
+ R"(matrix<float16_t, 4, 4> tint_symbol(uint4 buffer[3], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_2_yw = vector<float16_t, 2>(f16tof32(ubo_load_2 >> 16));
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_4_yw = vector<float16_t, 2>(f16tof32(ubo_load_4 >> 16));
+ const uint scalar_offset_3 = ((offset + 24u)) / 4;
+ uint4 ubo_load_7 = buffer[scalar_offset_3 / 4];
+ uint2 ubo_load_6 = ((scalar_offset_3 & 2) ? ubo_load_7.zw : ubo_load_7.xy);
+ vector<float16_t, 2> ubo_load_6_xz = vector<float16_t, 2>(f16tof32(ubo_load_6 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_6_yw = vector<float16_t, 2>(f16tof32(ubo_load_6 >> 16));
+ return matrix<float16_t, 4, 4>(vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]), vector<float16_t, 4>(ubo_load_2_xz[0], ubo_load_2_yw[0], ubo_load_2_xz[1], ubo_load_2_yw[1]), vector<float16_t, 4>(ubo_load_4_xz[0], ubo_load_4_yw[0], ubo_load_4_xz[1], ubo_load_4_yw[1]), vector<float16_t, 4>(ubo_load_6_xz[0], ubo_load_6_yw[0], ubo_load_6_xz[1], ubo_load_6_yw[1]));
+})"}));
+
+using HlslGeneratorImplTest_MemberAccessor_UniformBufferLoad_DynamicOffset =
+ HlslGeneratorImplTest_MemberAccessorWithParam<TypeCase>;
+
+TEST_P(HlslGeneratorImplTest_MemberAccessor_UniformBufferLoad_DynamicOffset, Test) {
+ // struct Inner {
+ // a : i32,
+ // b : <type>,
+ // c : vec4<i32>,
+ // };
+ // struct Data {
+ // arr : array<Inner, 4i>,
+ // }
+ // var<uniform> data : Data;
+ // data.arr[i].b;
+
+ auto p = GetParam();
+
+ Enable(ast::Extension::kF16);
+
+ auto* inner = Structure("Inner", utils::Vector{
+ Member("a", ty.i32()),
+ Member("b", p.member_type(ty)),
+ Member("c", ty.vec4(ty.i32())),
+ });
+
+ SetupUniformBuffer(utils::Vector{
+ Member("arr", ty.array(ty.Of(inner), 4_i)),
+ });
+
+ auto* i = Var("i", Expr(2_i));
+
+ SetupFunction(utils::Vector{
+ Decl(i),
+ Decl(Var("x", MemberAccessor(IndexAccessor(MemberAccessor("data", "arr"), i), "b"))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ HlslGeneratorImplTest_MemberAccessor,
+ HlslGeneratorImplTest_MemberAccessor_UniformBufferLoad_DynamicOffset,
+ testing::Values(
+ TypeCase{ty_u32, "x = data[scalar_offset / 4][scalar_offset % 4]"},
+ TypeCase{ty_f32, "x = asfloat(data[scalar_offset / 4][scalar_offset % 4])"},
+ TypeCase{ty_i32, "x = asint(data[scalar_offset / 4][scalar_offset % 4])"},
+ TypeCase{ty_f16, R"(const uint scalar_offset_bytes = (((32u * uint(i)) + 4u));
+ const uint scalar_offset_index = scalar_offset_bytes / 4;
+ float16_t x = float16_t(f16tof32(((data[scalar_offset_index / 4][scalar_offset_index % 4] >> (scalar_offset_bytes % 4 == 0 ? 0 : 16)) & 0xFFFF)));)"},
+ TypeCase{ty_vec2<u32>, R"(uint4 ubo_load = data[scalar_offset / 4];
+ uint2 x = ((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy);)"},
+ TypeCase{ty_vec2<f32>, R"(uint4 ubo_load = data[scalar_offset / 4];
+ float2 x = asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy));)"},
+ TypeCase{ty_vec2<i32>, R"(uint4 ubo_load = data[scalar_offset / 4];
+ int2 x = asint(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy));)"},
+ TypeCase{ty_vec2<f16>, R"(const uint scalar_offset = (((32u * uint(i)) + 4u)) / 4;
+ uint ubo_load = data[scalar_offset / 4][scalar_offset % 4];
+ vector<float16_t, 2> x = vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16)));)"},
+ TypeCase{ty_vec3<u32>, "x = data[scalar_offset / 4].xyz"},
+ TypeCase{ty_vec3<f32>, "x = asfloat(data[scalar_offset / 4].xyz)"},
+ TypeCase{ty_vec3<i32>, "x = asint(data[scalar_offset / 4].xyz)"},
+ TypeCase{ty_vec3<f16>, R"(const uint scalar_offset = (((32u * uint(i)) + 8u)) / 4;
+ uint4 ubo_load_1 = data[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ vector<float16_t, 3> x = vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]);)"},
+ TypeCase{ty_vec4<u32>, "x = data[scalar_offset / 4]"},
+ TypeCase{ty_vec4<f32>, "x = asfloat(data[scalar_offset / 4])"},
+ TypeCase{ty_vec4<i32>, "x = asint(data[scalar_offset / 4])"},
+ TypeCase{ty_vec4<f16>, R"(const uint scalar_offset = (((32u * uint(i)) + 8u)) / 4;
+ uint4 ubo_load_1 = data[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ vector<float16_t, 4> x = vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]);)"},
+ TypeCase{ty_mat2x2<f32>, R"(float2x2 tint_symbol(uint4 buffer[12], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load = buffer[scalar_offset / 4];
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+ return float2x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)));
+})"},
+ TypeCase{ty_mat2x3<f32>, R"(float2x3 tint_symbol(uint4 buffer[16], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ return float2x3(asfloat(buffer[scalar_offset / 4].xyz), asfloat(buffer[scalar_offset_1 / 4].xyz));
+})"},
+ TypeCase{ty_mat2x4<f32>, R"(float2x4 tint_symbol(uint4 buffer[16], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ return float2x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]));
+})"},
+ TypeCase{ty_mat3x2<f32>, R"(float3x2 tint_symbol(uint4 buffer[12], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load = buffer[scalar_offset / 4];
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+ return float3x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)));
+})"},
+ TypeCase{ty_mat3x3<f32>, R"(float3x3 tint_symbol(uint4 buffer[20], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ return float3x3(asfloat(buffer[scalar_offset / 4].xyz), asfloat(buffer[scalar_offset_1 / 4].xyz), asfloat(buffer[scalar_offset_2 / 4].xyz));
+})"},
+ TypeCase{ty_mat3x4<f32>, R"(float3x4 tint_symbol(uint4 buffer[20], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ return float3x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]), asfloat(buffer[scalar_offset_2 / 4]));
+})"},
+ TypeCase{ty_mat4x2<f32>, R"(float4x2 tint_symbol(uint4 buffer[16], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load = buffer[scalar_offset / 4];
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset_1 / 4];
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_2 = buffer[scalar_offset_2 / 4];
+ const uint scalar_offset_3 = ((offset + 24u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_3 / 4];
+ return float4x2(asfloat(((scalar_offset & 2) ? ubo_load.zw : ubo_load.xy)), asfloat(((scalar_offset_1 & 2) ? ubo_load_1.zw : ubo_load_1.xy)), asfloat(((scalar_offset_2 & 2) ? ubo_load_2.zw : ubo_load_2.xy)), asfloat(((scalar_offset_3 & 2) ? ubo_load_3.zw : ubo_load_3.xy)));
+})"},
+ TypeCase{ty_mat4x3<f32>, R"(float4x3 tint_symbol(uint4 buffer[24], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ const uint scalar_offset_3 = ((offset + 48u)) / 4;
+ return float4x3(asfloat(buffer[scalar_offset / 4].xyz), asfloat(buffer[scalar_offset_1 / 4].xyz), asfloat(buffer[scalar_offset_2 / 4].xyz), asfloat(buffer[scalar_offset_3 / 4].xyz));
+})"},
+ TypeCase{ty_mat4x4<f32>, R"(float4x4 tint_symbol(uint4 buffer[24], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const uint scalar_offset_1 = ((offset + 16u)) / 4;
+ const uint scalar_offset_2 = ((offset + 32u)) / 4;
+ const uint scalar_offset_3 = ((offset + 48u)) / 4;
+ return float4x4(asfloat(buffer[scalar_offset / 4]), asfloat(buffer[scalar_offset_1 / 4]), asfloat(buffer[scalar_offset_2 / 4]), asfloat(buffer[scalar_offset_3 / 4]));
+})"},
+ TypeCase{ty_mat2x2<f16>,
+ R"(matrix<float16_t, 2, 2> tint_symbol(uint4 buffer[8], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint ubo_load = buffer[scalar_offset / 4][scalar_offset % 4];
+ const uint scalar_offset_1 = ((offset + 4u)) / 4;
+ uint ubo_load_1 = buffer[scalar_offset_1 / 4][scalar_offset_1 % 4];
+ return matrix<float16_t, 2, 2>(vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_1 & 0xFFFF)), float16_t(f16tof32(ubo_load_1 >> 16))));
+})"},
+ TypeCase{ty_mat2x3<f16>,
+ R"(matrix<float16_t, 2, 3> tint_symbol(uint4 buffer[12], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ float16_t ubo_load_2_y = f16tof32(ubo_load_2[0] >> 16);
+ return matrix<float16_t, 2, 3>(vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]), vector<float16_t, 3>(ubo_load_2_xz[0], ubo_load_2_y, ubo_load_2_xz[1]));
+})"},
+ TypeCase{ty_mat2x4<f16>,
+ R"(matrix<float16_t, 2, 4> tint_symbol(uint4 buffer[12], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_2_yw = vector<float16_t, 2>(f16tof32(ubo_load_2 >> 16));
+ return matrix<float16_t, 2, 4>(vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]), vector<float16_t, 4>(ubo_load_2_xz[0], ubo_load_2_yw[0], ubo_load_2_xz[1], ubo_load_2_yw[1]));
+})"},
+ TypeCase{ty_mat3x2<f16>,
+ R"(matrix<float16_t, 3, 2> tint_symbol(uint4 buffer[8], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint ubo_load = buffer[scalar_offset / 4][scalar_offset % 4];
+ const uint scalar_offset_1 = ((offset + 4u)) / 4;
+ uint ubo_load_1 = buffer[scalar_offset_1 / 4][scalar_offset_1 % 4];
+ const uint scalar_offset_2 = ((offset + 8u)) / 4;
+ uint ubo_load_2 = buffer[scalar_offset_2 / 4][scalar_offset_2 % 4];
+ return matrix<float16_t, 3, 2>(vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_1 & 0xFFFF)), float16_t(f16tof32(ubo_load_1 >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_2 & 0xFFFF)), float16_t(f16tof32(ubo_load_2 >> 16))));
+})"},
+ TypeCase{ty_mat3x3<f16>,
+ R"(matrix<float16_t, 3, 3> tint_symbol(uint4 buffer[12], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ float16_t ubo_load_2_y = f16tof32(ubo_load_2[0] >> 16);
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ float16_t ubo_load_4_y = f16tof32(ubo_load_4[0] >> 16);
+ return matrix<float16_t, 3, 3>(vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]), vector<float16_t, 3>(ubo_load_2_xz[0], ubo_load_2_y, ubo_load_2_xz[1]), vector<float16_t, 3>(ubo_load_4_xz[0], ubo_load_4_y, ubo_load_4_xz[1]));
+})"},
+ TypeCase{ty_mat3x4<f16>,
+ R"(matrix<float16_t, 3, 4> tint_symbol(uint4 buffer[12], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_2_yw = vector<float16_t, 2>(f16tof32(ubo_load_2 >> 16));
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_4_yw = vector<float16_t, 2>(f16tof32(ubo_load_4 >> 16));
+ return matrix<float16_t, 3, 4>(vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]), vector<float16_t, 4>(ubo_load_2_xz[0], ubo_load_2_yw[0], ubo_load_2_xz[1], ubo_load_2_yw[1]), vector<float16_t, 4>(ubo_load_4_xz[0], ubo_load_4_yw[0], ubo_load_4_xz[1], ubo_load_4_yw[1]));
+})"},
+ TypeCase{ty_mat4x2<f16>,
+ R"(matrix<float16_t, 4, 2> tint_symbol(uint4 buffer[12], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint ubo_load = buffer[scalar_offset / 4][scalar_offset % 4];
+ const uint scalar_offset_1 = ((offset + 4u)) / 4;
+ uint ubo_load_1 = buffer[scalar_offset_1 / 4][scalar_offset_1 % 4];
+ const uint scalar_offset_2 = ((offset + 8u)) / 4;
+ uint ubo_load_2 = buffer[scalar_offset_2 / 4][scalar_offset_2 % 4];
+ const uint scalar_offset_3 = ((offset + 12u)) / 4;
+ uint ubo_load_3 = buffer[scalar_offset_3 / 4][scalar_offset_3 % 4];
+ return matrix<float16_t, 4, 2>(vector<float16_t, 2>(float16_t(f16tof32(ubo_load & 0xFFFF)), float16_t(f16tof32(ubo_load >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_1 & 0xFFFF)), float16_t(f16tof32(ubo_load_1 >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_2 & 0xFFFF)), float16_t(f16tof32(ubo_load_2 >> 16))), vector<float16_t, 2>(float16_t(f16tof32(ubo_load_3 & 0xFFFF)), float16_t(f16tof32(ubo_load_3 >> 16))));
+})"},
+ TypeCase{ty_mat4x3<f16>,
+ R"(matrix<float16_t, 4, 3> tint_symbol(uint4 buffer[16], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ float16_t ubo_load_y = f16tof32(ubo_load[0] >> 16);
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ float16_t ubo_load_2_y = f16tof32(ubo_load_2[0] >> 16);
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ float16_t ubo_load_4_y = f16tof32(ubo_load_4[0] >> 16);
+ const uint scalar_offset_3 = ((offset + 24u)) / 4;
+ uint4 ubo_load_7 = buffer[scalar_offset_3 / 4];
+ uint2 ubo_load_6 = ((scalar_offset_3 & 2) ? ubo_load_7.zw : ubo_load_7.xy);
+ vector<float16_t, 2> ubo_load_6_xz = vector<float16_t, 2>(f16tof32(ubo_load_6 & 0xFFFF));
+ float16_t ubo_load_6_y = f16tof32(ubo_load_6[0] >> 16);
+ return matrix<float16_t, 4, 3>(vector<float16_t, 3>(ubo_load_xz[0], ubo_load_y, ubo_load_xz[1]), vector<float16_t, 3>(ubo_load_2_xz[0], ubo_load_2_y, ubo_load_2_xz[1]), vector<float16_t, 3>(ubo_load_4_xz[0], ubo_load_4_y, ubo_load_4_xz[1]), vector<float16_t, 3>(ubo_load_6_xz[0], ubo_load_6_y, ubo_load_6_xz[1]));
+})"},
+ TypeCase{ty_mat4x4<f16>,
+ R"(matrix<float16_t, 4, 4> tint_symbol(uint4 buffer[16], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ uint4 ubo_load_1 = buffer[scalar_offset / 4];
+ uint2 ubo_load = ((scalar_offset & 2) ? ubo_load_1.zw : ubo_load_1.xy);
+ vector<float16_t, 2> ubo_load_xz = vector<float16_t, 2>(f16tof32(ubo_load & 0xFFFF));
+ vector<float16_t, 2> ubo_load_yw = vector<float16_t, 2>(f16tof32(ubo_load >> 16));
+ const uint scalar_offset_1 = ((offset + 8u)) / 4;
+ uint4 ubo_load_3 = buffer[scalar_offset_1 / 4];
+ uint2 ubo_load_2 = ((scalar_offset_1 & 2) ? ubo_load_3.zw : ubo_load_3.xy);
+ vector<float16_t, 2> ubo_load_2_xz = vector<float16_t, 2>(f16tof32(ubo_load_2 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_2_yw = vector<float16_t, 2>(f16tof32(ubo_load_2 >> 16));
+ const uint scalar_offset_2 = ((offset + 16u)) / 4;
+ uint4 ubo_load_5 = buffer[scalar_offset_2 / 4];
+ uint2 ubo_load_4 = ((scalar_offset_2 & 2) ? ubo_load_5.zw : ubo_load_5.xy);
+ vector<float16_t, 2> ubo_load_4_xz = vector<float16_t, 2>(f16tof32(ubo_load_4 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_4_yw = vector<float16_t, 2>(f16tof32(ubo_load_4 >> 16));
+ const uint scalar_offset_3 = ((offset + 24u)) / 4;
+ uint4 ubo_load_7 = buffer[scalar_offset_3 / 4];
+ uint2 ubo_load_6 = ((scalar_offset_3 & 2) ? ubo_load_7.zw : ubo_load_7.xy);
+ vector<float16_t, 2> ubo_load_6_xz = vector<float16_t, 2>(f16tof32(ubo_load_6 & 0xFFFF));
+ vector<float16_t, 2> ubo_load_6_yw = vector<float16_t, 2>(f16tof32(ubo_load_6 >> 16));
+ return matrix<float16_t, 4, 4>(vector<float16_t, 4>(ubo_load_xz[0], ubo_load_yw[0], ubo_load_xz[1], ubo_load_yw[1]), vector<float16_t, 4>(ubo_load_2_xz[0], ubo_load_2_yw[0], ubo_load_2_xz[1], ubo_load_2_yw[1]), vector<float16_t, 4>(ubo_load_4_xz[0], ubo_load_4_yw[0], ubo_load_4_xz[1], ubo_load_4_yw[1]), vector<float16_t, 4>(ubo_load_6_xz[0], ubo_load_6_yw[0], ubo_load_6_xz[1], ubo_load_6_yw[1]));
+})"}));
using HlslGeneratorImplTest_MemberAccessor_StorageBufferStore =
HlslGeneratorImplTest_MemberAccessorWithParam<TypeCase>;
TEST_P(HlslGeneratorImplTest_MemberAccessor_StorageBufferStore, Test) {
// struct Data {
- // a : i32;
- // b : <type>;
+ // a : i32,
+ // b : <type>,
// };
// var<storage> data : Data;
// data.b = <type>();
auto p = GetParam();
+ Enable(ast::Extension::kF16);
+
SetupStorageBuffer(utils::Vector{
Member("a", ty.i32()),
Member("b", p.member_type(ty)),
@@ -243,73 +1010,123 @@
EXPECT_THAT(gen.result(), HasSubstr(p.expected));
}
-INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_MemberAccessor,
- HlslGeneratorImplTest_MemberAccessor_StorageBufferStore,
- testing::Values(TypeCase{ty_u32, "data.Store(4u, asuint(value))"},
- TypeCase{ty_f32, "data.Store(4u, asuint(value))"},
- TypeCase{ty_i32, "data.Store(4u, asuint(value))"},
- TypeCase{ty_vec2<u32>, "data.Store2(8u, asuint(value))"},
- TypeCase{ty_vec2<f32>, "data.Store2(8u, asuint(value))"},
- TypeCase{ty_vec2<i32>, "data.Store2(8u, asuint(value))"},
- TypeCase{ty_vec3<u32>, "data.Store3(16u, asuint(value))"},
- TypeCase{ty_vec3<f32>, "data.Store3(16u, asuint(value))"},
- TypeCase{ty_vec3<i32>, "data.Store3(16u, asuint(value))"},
- TypeCase{ty_vec4<u32>, "data.Store4(16u, asuint(value))"},
- TypeCase{ty_vec4<f32>, "data.Store4(16u, asuint(value))"},
- TypeCase{ty_vec4<i32>, "data.Store4(16u, asuint(value))"},
- TypeCase{ty_mat2x2<f32>, R"({
+INSTANTIATE_TEST_SUITE_P(
+ HlslGeneratorImplTest_MemberAccessor,
+ HlslGeneratorImplTest_MemberAccessor_StorageBufferStore,
+ testing::Values(TypeCase{ty_u32, "data.Store(4u, asuint(value))"},
+ TypeCase{ty_f32, "data.Store(4u, asuint(value))"},
+ TypeCase{ty_i32, "data.Store(4u, asuint(value))"},
+ TypeCase{ty_f16, "data.Store<float16_t>(4u, value)"},
+ TypeCase{ty_vec2<u32>, "data.Store2(8u, asuint(value))"},
+ TypeCase{ty_vec2<f32>, "data.Store2(8u, asuint(value))"},
+ TypeCase{ty_vec2<i32>, "data.Store2(8u, asuint(value))"},
+ TypeCase{ty_vec2<f16>, "data.Store<vector<float16_t, 2> >(4u, value)"},
+ TypeCase{ty_vec3<u32>, "data.Store3(16u, asuint(value))"},
+ TypeCase{ty_vec3<f32>, "data.Store3(16u, asuint(value))"},
+ TypeCase{ty_vec3<i32>, "data.Store3(16u, asuint(value))"},
+ TypeCase{ty_vec3<f16>, "data.Store<vector<float16_t, 3> >(8u, value)"},
+ TypeCase{ty_vec4<u32>, "data.Store4(16u, asuint(value))"},
+ TypeCase{ty_vec4<f32>, "data.Store4(16u, asuint(value))"},
+ TypeCase{ty_vec4<i32>, "data.Store4(16u, asuint(value))"},
+ TypeCase{ty_vec4<f16>, "data.Store<vector<float16_t, 4> >(8u, value)"},
+ TypeCase{ty_mat2x2<f32>, R"({
buffer.Store2((offset + 0u), asuint(value[0u]));
buffer.Store2((offset + 8u), asuint(value[1u]));
})"},
- TypeCase{ty_mat2x3<f32>, R"({
+ TypeCase{ty_mat2x3<f32>, R"({
buffer.Store3((offset + 0u), asuint(value[0u]));
buffer.Store3((offset + 16u), asuint(value[1u]));
})"},
- TypeCase{ty_mat2x4<f32>, R"({
+ TypeCase{ty_mat2x4<f32>, R"({
buffer.Store4((offset + 0u), asuint(value[0u]));
buffer.Store4((offset + 16u), asuint(value[1u]));
})"},
- TypeCase{ty_mat3x2<f32>, R"({
+ TypeCase{ty_mat3x2<f32>, R"({
buffer.Store2((offset + 0u), asuint(value[0u]));
buffer.Store2((offset + 8u), asuint(value[1u]));
buffer.Store2((offset + 16u), asuint(value[2u]));
})"},
- TypeCase{ty_mat3x3<f32>, R"({
+ TypeCase{ty_mat3x3<f32>, R"({
buffer.Store3((offset + 0u), asuint(value[0u]));
buffer.Store3((offset + 16u), asuint(value[1u]));
buffer.Store3((offset + 32u), asuint(value[2u]));
})"},
- TypeCase{ty_mat3x4<f32>, R"({
+ TypeCase{ty_mat3x4<f32>, R"({
buffer.Store4((offset + 0u), asuint(value[0u]));
buffer.Store4((offset + 16u), asuint(value[1u]));
buffer.Store4((offset + 32u), asuint(value[2u]));
})"},
- TypeCase{ty_mat4x2<f32>, R"({
+ TypeCase{ty_mat4x2<f32>, R"({
buffer.Store2((offset + 0u), asuint(value[0u]));
buffer.Store2((offset + 8u), asuint(value[1u]));
buffer.Store2((offset + 16u), asuint(value[2u]));
buffer.Store2((offset + 24u), asuint(value[3u]));
})"},
- TypeCase{ty_mat4x3<f32>, R"({
+ TypeCase{ty_mat4x3<f32>, R"({
buffer.Store3((offset + 0u), asuint(value[0u]));
buffer.Store3((offset + 16u), asuint(value[1u]));
buffer.Store3((offset + 32u), asuint(value[2u]));
buffer.Store3((offset + 48u), asuint(value[3u]));
})"},
- TypeCase{ty_mat4x4<f32>, R"({
+ TypeCase{ty_mat4x4<f32>, R"({
buffer.Store4((offset + 0u), asuint(value[0u]));
buffer.Store4((offset + 16u), asuint(value[1u]));
buffer.Store4((offset + 32u), asuint(value[2u]));
buffer.Store4((offset + 48u), asuint(value[3u]));
+})"},
+ TypeCase{ty_mat2x2<f16>, R"({
+ buffer.Store<vector<float16_t, 2> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 2> >((offset + 4u), value[1u]);
+})"},
+ TypeCase{ty_mat2x3<f16>, R"({
+ buffer.Store<vector<float16_t, 3> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 3> >((offset + 8u), value[1u]);
+})"},
+ TypeCase{ty_mat2x4<f16>, R"({
+ buffer.Store<vector<float16_t, 4> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 4> >((offset + 8u), value[1u]);
+})"},
+ TypeCase{ty_mat3x2<f16>, R"({
+ buffer.Store<vector<float16_t, 2> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 2> >((offset + 4u), value[1u]);
+ buffer.Store<vector<float16_t, 2> >((offset + 8u), value[2u]);
+})"},
+ TypeCase{ty_mat3x3<f16>, R"({
+ buffer.Store<vector<float16_t, 3> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 3> >((offset + 8u), value[1u]);
+ buffer.Store<vector<float16_t, 3> >((offset + 16u), value[2u]);
+})"},
+ TypeCase{ty_mat3x4<f16>, R"({
+ buffer.Store<vector<float16_t, 4> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 4> >((offset + 8u), value[1u]);
+ buffer.Store<vector<float16_t, 4> >((offset + 16u), value[2u]);
+})"},
+ TypeCase{ty_mat4x2<f16>, R"({
+ buffer.Store<vector<float16_t, 2> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 2> >((offset + 4u), value[1u]);
+ buffer.Store<vector<float16_t, 2> >((offset + 8u), value[2u]);
+ buffer.Store<vector<float16_t, 2> >((offset + 12u), value[3u]);
+})"},
+ TypeCase{ty_mat4x3<f16>, R"({
+ buffer.Store<vector<float16_t, 3> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 3> >((offset + 8u), value[1u]);
+ buffer.Store<vector<float16_t, 3> >((offset + 16u), value[2u]);
+ buffer.Store<vector<float16_t, 3> >((offset + 24u), value[3u]);
+})"},
+ TypeCase{ty_mat4x4<f16>, R"({
+ buffer.Store<vector<float16_t, 4> >((offset + 0u), value[0u]);
+ buffer.Store<vector<float16_t, 4> >((offset + 8u), value[1u]);
+ buffer.Store<vector<float16_t, 4> >((offset + 16u), value[2u]);
+ buffer.Store<vector<float16_t, 4> >((offset + 24u), value[3u]);
})"}));
TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_Matrix_Empty) {
// struct Data {
- // z : f32;
- // a : mat2x3<f32>;
+ // a : f32,
+ // b : mat2x3<f32>,
// };
// var<storage> data : Data;
- // data.a = mat2x3<f32>();
+ // data.b = mat2x3<f32>();
SetupStorageBuffer(utils::Vector{
Member("a", ty.i32()),
@@ -339,10 +1156,10 @@
EXPECT_EQ(gen.result(), expected);
}
-TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_Matrix_Single_Element) {
+TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_Matrix_F32_Single_Element) {
// struct Data {
- // z : f32;
- // a : mat4x3<f32>;
+ // z : f32,
+ // a : mat4x3<f32>,
// };
// var<storage> data : Data;
// data.a[2i][1i];
@@ -370,17 +1187,119 @@
EXPECT_EQ(gen.result(), expected);
}
-TEST_F(HlslGeneratorImplTest_MemberAccessor,
- EmitExpression_IndexAccessor_StorageBuffer_Load_Int_FromArray) {
+TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_Matrix_F16_Single_Element) {
// struct Data {
- // a : array<i32, 5>;
+ // z : f16,
+ // a : mat4x3<f16>,
+ // };
+ // var<storage> data : Data;
+ // data.a[2i][1i];
+
+ Enable(ast::Extension::kF16);
+
+ SetupStorageBuffer(utils::Vector{
+ Member("z", ty.f16()),
+ Member("a", ty.mat4x3<f16>()),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", IndexAccessor(IndexAccessor(MemberAccessor("data", "a"), 2_i), 1_i))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(RWByteAddressBuffer data : register(u0, space1);
+
+void main() {
+ float16_t x = data.Load<float16_t>(26u);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_Matrix_F32_Single_Element) {
+ // struct Data {
+ // z : f32,
+ // a : mat4x3<f32>,
+ // };
+ // var<uniform> data : Data;
+ // data.a[2i][1i];
+
+ SetupUniformBuffer(utils::Vector{
+ Member("z", ty.f32()),
+ Member("a", ty.mat4x3<f32>()),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", IndexAccessor(IndexAccessor(MemberAccessor("data", "a"), 2_i), 1_i))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[5];
+};
+
+void main() {
+ float x = asfloat(data[3].y);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_Matrix_F16_Single_Element) {
+ // struct Data {
+ // z : f16,
+ // a : mat4x3<f16>,
+ // };
+ // var<uniform> data : Data;
+ // data.a[2i][1i];
+
+ Enable(ast::Extension::kF16);
+
+ SetupUniformBuffer(utils::Vector{
+ Member("z", ty.f16()),
+ Member("a", ty.mat4x3<f16>()),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", IndexAccessor(IndexAccessor(MemberAccessor("data", "a"), 2_i), 1_i))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[3];
+};
+
+void main() {
+ float16_t x = float16_t(f16tof32(((data[1].z >> 16) & 0xFFFF)));
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor,
+ EmitExpression_IndexAccessor_StorageBuffer_Load_I32_FromArray) {
+ // struct Data {
+ // z : f32,
+ // a : array<i32, 5i>,
// };
// var<storage> data : Data;
// data.a[2];
SetupStorageBuffer(utils::Vector{
Member("z", ty.f32()),
- Member("a", ty.array<i32, 5>(4)),
+ Member("a", ty.array(ty.i32(), 5_i)),
});
SetupFunction(utils::Vector{
@@ -402,16 +1321,154 @@
}
TEST_F(HlslGeneratorImplTest_MemberAccessor,
- EmitExpression_IndexAccessor_StorageBuffer_Load_Int_FromArray_ExprIdx) {
+ EmitExpression_IndexAccessor_UniformBuffer_Load_Vec4_I32_FromArray) {
// struct Data {
- // a : array<i32, 5>;
+ // z : f32,
+ // a : array<vec4<i32>, 5i>,
+ // };
+ // var<uniform> data : Data;
+ // data.a[2];
+
+ SetupUniformBuffer(utils::Vector{
+ Member("z", ty.f32()),
+ Member("a", ty.array(ty.vec4(ty.i32()), 5_i)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", IndexAccessor(MemberAccessor("data", "a"), 2_i))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[6];
+};
+
+void main() {
+ int4 x = asint(data[3]);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor,
+ EmitExpression_IndexAccessor_StorageBuffer_Load_Struct_FromArray) {
+ // struct Inner {
+ // @size(16i) @align(16i)
+ // v : i32,
+ // };
+ // struct Data {
+ // z : f32,
+ // a : array<Inner, 5i>,
+ // };
+ // var<storage> data : Data;
+ // data.a[2i];
+
+ auto* elem_type = Structure(
+ "Inner", utils::Vector{
+ Member("v", ty.i32(), utils::Vector{MemberSize(16_i), MemberAlign(16_i)}),
+ });
+
+ SetupStorageBuffer(utils::Vector{
+ Member("z", ty.f32()),
+ Member("a", ty.array(ty.Of(elem_type), 5_i)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", IndexAccessor(MemberAccessor("data", "a"), 2_i))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(struct Inner {
+ int v;
+};
+
+RWByteAddressBuffer data : register(u0, space1);
+
+Inner tint_symbol(RWByteAddressBuffer buffer, uint offset) {
+ const Inner tint_symbol_2 = {asint(buffer.Load((offset + 0u)))};
+ return tint_symbol_2;
+}
+
+void main() {
+ Inner x = tint_symbol(data, 48u);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor,
+ EmitExpression_IndexAccessor_UniformBuffer_Load_Struct_FromArray) {
+ // struct Inner {
+ // @size(16i) @align(16i)
+ // v : i32,
+ // };
+ // struct Data {
+ // z : f32,
+ // a : array<Inner, 5i>,
+ // };
+ // var<uniform> data : Data;
+ // data.a[2i];
+
+ auto* elem_type = Structure(
+ "Inner", utils::Vector{
+ Member("v", ty.i32(), utils::Vector{MemberSize(16_i), MemberAlign(16_i)}),
+ });
+
+ SetupUniformBuffer(utils::Vector{
+ Member("z", ty.f32()),
+ Member("a", ty.array(ty.Of(elem_type), 5_i)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", IndexAccessor(MemberAccessor("data", "a"), 2_i))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(struct Inner {
+ int v;
+};
+
+cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[6];
+};
+
+Inner tint_symbol(uint4 buffer[6], uint offset) {
+ const uint scalar_offset = ((offset + 0u)) / 4;
+ const Inner tint_symbol_2 = {asint(buffer[scalar_offset / 4][scalar_offset % 4])};
+ return tint_symbol_2;
+}
+
+void main() {
+ Inner x = tint_symbol(data, 48u);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor,
+ EmitExpression_IndexAccessor_StorageBuffer_Load_I32_FromArray_ExprIdx) {
+ // struct Data {
+ // z : f32,
+ // a : array<i32, 5i>,
// };
// var<storage> data : Data;
// data.a[(2i + 4i) - 3i];
SetupStorageBuffer(utils::Vector{
Member("z", ty.f32()),
- Member("a", ty.array<i32, 5>(4)),
+ Member("a", ty.array(ty.i32(), 5_i)),
});
SetupFunction(utils::Vector{
@@ -438,16 +1495,57 @@
EXPECT_EQ(gen.result(), expected);
}
+TEST_F(HlslGeneratorImplTest_MemberAccessor,
+ EmitExpression_IndexAccessor_UniformBuffer_Load_Vec4_I32_FromArray_ExprIdx) {
+ // struct Data {
+ // z : f32,
+ // a : array<vec4<i32>, 5i>,
+ // };
+ // var<uniform> data : Data;
+ // data.a[(2i + 4i) - 3i];
+
+ SetupUniformBuffer(utils::Vector{
+ Member("z", ty.f32()),
+ Member("a", ty.array(ty.vec4(ty.i32()), 5_i)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("a", Expr(2_i))),
+ Decl(Var("b", Expr(4_i))),
+ Decl(Var("c", Expr(3_i))),
+ Decl(Var("x", IndexAccessor(MemberAccessor("data", "a"), Sub(Add("a", "b"), "c")))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[6];
+};
+
+void main() {
+ int a = 2;
+ int b = 4;
+ int c = 3;
+ const uint scalar_offset = ((16u + (16u * uint(((a + b) - c))))) / 4;
+ int4 x = asint(data[scalar_offset / 4]);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_ToArray) {
// struct Data {
- // a : array<i32, 5>;
+ // a : array<i32, 5i>,
// };
// var<storage> data : Data;
- // data.a[2] = 2;
+ // data.a[2i] = 2i;
SetupStorageBuffer(utils::Vector{
Member("z", ty.f32()),
- Member("a", ty.array<i32, 5>(4)),
+ Member("a", ty.array(ty.i32(), 5_i)),
});
SetupFunction(utils::Vector{
@@ -470,23 +1568,23 @@
TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel) {
// struct Inner {
- // a : vec3<i32>;
- // b : vec3<f32>;
+ // a : vec3<i32>,
+ // b : vec3<f32>,
// };
// struct Data {
- // var c : array<Inner, 4u>;
+ // c : array<Inner, 4u>,
// };
//
- // var<storage> data : Pre;
- // data.c[2].b
+ // var<storage> data : Data;
+ // data.c[2i].b
auto* inner = Structure("Inner", utils::Vector{
- Member("a", ty.vec3<f32>()),
+ Member("a", ty.vec3<i32>()),
Member("b", ty.vec3<f32>()),
});
SetupStorageBuffer(utils::Vector{
- Member("c", ty.array(ty.Of(inner), 4_u, 32)),
+ Member("c", ty.array(ty.Of(inner), 4_u)),
});
SetupFunction(utils::Vector{
@@ -507,31 +1605,72 @@
EXPECT_EQ(gen.result(), expected);
}
-TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Swizzle) {
+TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_MultiLevel) {
// struct Inner {
- // a : vec3<i32>;
- // b : vec3<f32>;
+ // a : vec3<i32>,
+ // b : vec3<f32>,
// };
// struct Data {
- // var c : array<Inner, 4u>;
+ // var c : array<Inner, 4u>,
// };
//
- // var<storage> data : Pre;
- // data.c[2].b.xy
+ // var<storage> data : Data;
+ // data.c[2i].b
auto* inner = Structure("Inner", utils::Vector{
- Member("a", ty.vec3<f32>()),
+ Member("a", ty.vec3<i32>()),
+ Member("b", ty.vec3<f32>()),
+ });
+
+ SetupUniformBuffer(utils::Vector{
+ Member("c", ty.array(ty.Of(inner), 4_u)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x", MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[8];
+};
+
+void main() {
+ float3 x = asfloat(data[5].xyz);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Swizzle) {
+ // struct Inner {
+ // a : vec3<i32>,
+ // b : vec3<f32>,
+ // };
+ // struct Data {
+ // var c : array<Inner, 4u>,
+ // };
+ //
+ // var<storage> data : Data;
+ // data.c[2i].b.yx
+
+ auto* inner = Structure("Inner", utils::Vector{
+ Member("a", ty.vec3<i32>()),
Member("b", ty.vec3<f32>()),
});
SetupStorageBuffer(utils::Vector{
- Member("c", ty.array(ty.Of(inner), 4_u, 32)),
+ Member("c", ty.array(ty.Of(inner), 4_u)),
});
SetupFunction(utils::Vector{
Decl(Var("x",
MemberAccessor(
- MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"), "xy"))),
+ MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"), "yx"))),
});
GeneratorImpl& gen = SanitizeAndBuild();
@@ -541,7 +1680,50 @@
R"(RWByteAddressBuffer data : register(u0, space1);
void main() {
- float2 x = asfloat(data.Load3(80u)).xy;
+ float2 x = asfloat(data.Load3(80u)).yx;
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_MultiLevel_Swizzle) {
+ // struct Inner {
+ // a : vec3<i32>,
+ // b : vec3<f32>,
+ // };
+ // struct Data {
+ // var c : array<Inner, 4u>,
+ // };
+ //
+ // var<uniform> data : Data;
+ // data.c[2i].b.yx
+
+ auto* inner = Structure("Inner", utils::Vector{
+ Member("a", ty.vec3<i32>()),
+ Member("b", ty.vec3<f32>()),
+ });
+
+ SetupUniformBuffer(utils::Vector{
+ Member("c", ty.array(ty.Of(inner), 4_u)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x",
+ MemberAccessor(
+ MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"), "yx"))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[8];
+};
+
+void main() {
+ float2 x = asfloat(data[5].xyz).yx;
return;
}
)";
@@ -551,23 +1733,23 @@
TEST_F(HlslGeneratorImplTest_MemberAccessor,
StorageBuffer_Load_MultiLevel_Swizzle_SingleLetter) { // NOLINT
// struct Inner {
- // a : vec3<i32>;
- // b : vec3<f32>;
+ // a : vec3<i32>,
+ // b : vec3<f32>,
// };
// struct Data {
- // var c : array<Inner, 4u>;
+ // var c : array<Inner, 4u>,
// };
//
- // var<storage> data : Pre;
- // data.c[2].b.g
+ // var<storage> data : Data;
+ // data.c[2i].b.g
auto* inner = Structure("Inner", utils::Vector{
- Member("a", ty.vec3<f32>()),
+ Member("a", ty.vec3<i32>()),
Member("b", ty.vec3<f32>()),
});
SetupStorageBuffer(utils::Vector{
- Member("c", ty.array(ty.Of(inner), 4_u, 32)),
+ Member("c", ty.array(ty.Of(inner), 4_u)),
});
SetupFunction(utils::Vector{
@@ -590,25 +1772,69 @@
EXPECT_EQ(gen.result(), expected);
}
-TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Index) {
+TEST_F(HlslGeneratorImplTest_MemberAccessor,
+ UniformBuffer_Load_MultiLevel_Swizzle_SingleLetter) { // NOLINT
// struct Inner {
- // a : vec3<i32>;
- // b : vec3<f32>;
+ // a : vec3<i32>,
+ // b : vec3<f32>,
// };
// struct Data {
- // var c : array<Inner, 4u>;
+ // var c : array<Inner, 4u>,
// };
//
- // var<storage> data : Pre;
- // data.c[2].b[1]
+ // var<uniform> data : Data;
+ // data.c[2i].b.g
auto* inner = Structure("Inner", utils::Vector{
- Member("a", ty.vec3<f32>()),
+ Member("a", ty.vec3<i32>()),
+ Member("b", ty.vec3<f32>()),
+ });
+
+ SetupUniformBuffer(utils::Vector{
+ Member("c", ty.array(ty.Of(inner), 4_u)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x",
+ MemberAccessor(
+ MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"), "g"))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[8];
+};
+
+void main() {
+ float x = asfloat(data[5].y);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Index) {
+ // struct Inner {
+ // a : vec3<i32>,
+ // b : vec3<f32>,
+ // };
+ // struct Data {
+ // var c : array<Inner, 4u>,
+ // };
+ //
+ // var<storage> data : Data;
+ // data.c[2i].b[1i]
+
+ auto* inner = Structure("Inner", utils::Vector{
+ Member("a", ty.vec3<i32>()),
Member("b", ty.vec3<f32>()),
});
SetupStorageBuffer(utils::Vector{
- Member("c", ty.array(ty.Of(inner), 4_u, 32)),
+ Member("c", ty.array(ty.Of(inner), 4_u)),
});
SetupFunction(utils::Vector{
@@ -631,25 +1857,68 @@
EXPECT_EQ(gen.result(), expected);
}
-TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_MultiLevel) {
+TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_MultiLevel_Index) {
// struct Inner {
- // a : vec3<i32>;
- // b : vec3<f32>;
+ // a : vec3<i32>,
+ // b : vec3<f32>,
// };
// struct Data {
- // var c : array<Inner, 4u>;
+ // var c : array<Inner, 4u>,
+ // };
+ //
+ // var<uniform> data : Data;
+ // data.c[2i].b[1i]
+
+ auto* inner = Structure("Inner", utils::Vector{
+ Member("a", ty.vec3<i32>()),
+ Member("b", ty.vec3<f32>()),
+ });
+
+ SetupUniformBuffer(utils::Vector{
+ Member("c", ty.array(ty.Of(inner), 4_u)),
+ });
+
+ SetupFunction(utils::Vector{
+ Decl(Var("x",
+ IndexAccessor(MemberAccessor(IndexAccessor(MemberAccessor("data", "c"), 2_i), "b"),
+ 1_i))),
+ });
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ auto* expected =
+ R"(cbuffer cbuffer_data : register(b1, space1) {
+ uint4 data[8];
+};
+
+void main() {
+ float x = asfloat(data[5].y);
+ return;
+}
+)";
+ EXPECT_EQ(gen.result(), expected);
+}
+
+TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_MultiLevel) {
+ // struct Inner {
+ // a : vec3<i32>,
+ // b : vec3<f32>,
+ // };
+ // struct Data {
+ // var c : array<Inner, 4u>,
// };
//
// var<storage> data : Pre;
- // data.c[2].b = vec3<f32>(1_f, 2_f, 3_f);
+ // data.c[2i].b = vec3<f32>(1_f, 2_f, 3_f);
auto* inner = Structure("Inner", utils::Vector{
- Member("a", ty.vec3<f32>()),
+ Member("a", ty.vec3<i32>()),
Member("b", ty.vec3<f32>()),
});
SetupStorageBuffer(utils::Vector{
- Member("c", ty.array(ty.Of(inner), 4_u, 32)),
+ Member("c", ty.array(ty.Of(inner), 4_u)),
});
SetupFunction(utils::Vector{
@@ -673,15 +1942,15 @@
TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_Swizzle_SingleLetter) {
// struct Inner {
- // a : vec3<i32>;
- // b : vec3<f32>;
+ // a : vec3<i32>,
+ // b : vec3<f32>,
// };
// struct Data {
- // var c : array<Inner, 4u>;
+ // var c : array<Inner, 4u>,
// };
//
// var<storage> data : Pre;
- // data.c[2].b.y = 1.f;
+ // data.c[2i].b.y = 1.f;
auto* inner = Structure("Inner", utils::Vector{
Member("a", ty.vec3<i32>()),
@@ -689,7 +1958,7 @@
});
SetupStorageBuffer(utils::Vector{
- Member("c", ty.array(ty.Of(inner), 4_u, 32)),
+ Member("c", ty.array(ty.Of(inner), 4_u)),
});
SetupFunction(utils::Vector{
diff --git a/src/tint/writer/msl/generator_impl_builtin_test.cc b/src/tint/writer/msl/generator_impl_builtin_test.cc
index c611d6b..7a69a14 100644
--- a/src/tint/writer/msl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/msl/generator_impl_builtin_test.cc
@@ -416,19 +416,19 @@
using namespace metal;
-struct modf_result {
+struct modf_result_f32 {
float fract;
float whole;
};
-modf_result tint_modf(float param_0) {
- modf_result result;
+modf_result_f32 tint_modf(float param_0) {
+ modf_result_f32 result;
result.fract = modf(param_0, result.whole);
return result;
}
kernel void test_function() {
float const f = 1.5f;
- modf_result const v = tint_modf(f);
+ modf_result_f32 const v = tint_modf(f);
return;
}
@@ -478,19 +478,19 @@
using namespace metal;
-struct modf_result_vec3 {
+struct modf_result_vec3_f32 {
float3 fract;
float3 whole;
};
-modf_result_vec3 tint_modf(float3 param_0) {
- modf_result_vec3 result;
+modf_result_vec3_f32 tint_modf(float3 param_0) {
+ modf_result_vec3_f32 result;
result.fract = modf(param_0, result.whole);
return result;
}
kernel void test_function() {
float3 const f = float3(1.5f, 2.5f, 3.5f);
- modf_result_vec3 const v = tint_modf(f);
+ modf_result_vec3_f32 const v = tint_modf(f);
return;
}
@@ -539,12 +539,12 @@
using namespace metal;
-struct modf_result {
+struct modf_result_f32 {
float fract;
float whole;
};
kernel void test_function() {
- modf_result const v = modf_result{.fract=0.5f, .whole=1.0f};
+ modf_result_f32 const v = modf_result_f32{.fract=0.5f, .whole=1.0f};
return;
}
@@ -585,12 +585,12 @@
using namespace metal;
-struct modf_result_vec3 {
+struct modf_result_vec3_f32 {
float3 fract;
float3 whole;
};
kernel void test_function() {
- modf_result_vec3 const v = modf_result_vec3{.fract=float3(0.5f), .whole=float3(1.0f, 2.0f, 3.0f)};
+ modf_result_vec3_f32 const v = modf_result_vec3_f32{.fract=float3(0.5f), .whole=float3(1.0f, 2.0f, 3.0f)};
return;
}
@@ -621,9 +621,9 @@
)");
}
-TEST_F(MslGeneratorImplTest, Frexp_Scalar_f32) {
- auto* call = Call("frexp", 1_f);
- WrapInFunction(CallStmt(call));
+TEST_F(MslGeneratorImplTest, Runtime_Frexp_Scalar_f32) {
+ WrapInFunction(Var("f", Expr(1_f)), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -632,29 +632,30 @@
using namespace metal;
-struct frexp_result {
+struct frexp_result_f32 {
float fract;
int exp;
};
-frexp_result tint_frexp(float param_0) {
- frexp_result result;
+frexp_result_f32 tint_frexp(float param_0) {
+ frexp_result_f32 result;
result.fract = frexp(param_0, result.exp);
return result;
}
kernel void test_function() {
- tint_frexp(1.0f);
+ float f = 1.0f;
+ frexp_result_f32 v = tint_frexp(f);
return;
}
)");
}
-TEST_F(MslGeneratorImplTest, Frexp_Scalar_f16) {
+TEST_F(MslGeneratorImplTest, Runtime_Frexp_Scalar_f16) {
Enable(ast::Extension::kF16);
- auto* call = Call("frexp", 1_h);
- WrapInFunction(CallStmt(call));
+ WrapInFunction(Var("f", Expr(1_h)), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -674,16 +675,17 @@
}
kernel void test_function() {
- tint_frexp(1.0h);
+ half f = 1.0h;
+ frexp_result_f16 v = tint_frexp(f);
return;
}
)");
}
-TEST_F(MslGeneratorImplTest, Frexp_Vector_f32) {
- auto* call = Call("frexp", vec3<f32>());
- WrapInFunction(CallStmt(call));
+TEST_F(MslGeneratorImplTest, Runtime_Frexp_Vector_f32) {
+ WrapInFunction(Var("f", Expr(vec3<f32>())), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -692,29 +694,30 @@
using namespace metal;
-struct frexp_result_vec3 {
+struct frexp_result_vec3_f32 {
float3 fract;
int3 exp;
};
-frexp_result_vec3 tint_frexp(float3 param_0) {
- frexp_result_vec3 result;
+frexp_result_vec3_f32 tint_frexp(float3 param_0) {
+ frexp_result_vec3_f32 result;
result.fract = frexp(param_0, result.exp);
return result;
}
kernel void test_function() {
- tint_frexp(float3(0.0f));
+ float3 f = float3(0.0f);
+ frexp_result_vec3_f32 v = tint_frexp(f);
return;
}
)");
}
-TEST_F(MslGeneratorImplTest, Frexp_Vector_f16) {
+TEST_F(MslGeneratorImplTest, Runtime_Frexp_Vector_f16) {
Enable(ast::Extension::kF16);
- auto* call = Call("frexp", vec3<f16>());
- WrapInFunction(CallStmt(call));
+ WrapInFunction(Var("f", Expr(vec3<f16>())), //
+ Var("v", Call("frexp", "f")));
GeneratorImpl& gen = SanitizeAndBuild();
@@ -734,7 +737,100 @@
}
kernel void test_function() {
- tint_frexp(half3(0.0h));
+ half3 f = half3(0.0h);
+ frexp_result_vec3_f16 v = tint_frexp(f);
+ return;
+}
+
+)");
+}
+
+TEST_F(MslGeneratorImplTest, Const_Frexp_Scalar_f32) {
+ WrapInFunction(Decl(Let("v", Call("frexp", 1_f))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_f32 {
+ float fract;
+ int exp;
+};
+kernel void test_function() {
+ frexp_result_f32 const v = frexp_result_f32{.fract=0.5f, .exp=1};
+ return;
+}
+
+)");
+}
+
+TEST_F(MslGeneratorImplTest, Const_Frexp_Scalar_f16) {
+ Enable(ast::Extension::kF16);
+
+ WrapInFunction(Decl(Let("v", Call("frexp", 1_h))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_f16 {
+ half fract;
+ int exp;
+};
+kernel void test_function() {
+ frexp_result_f16 const v = frexp_result_f16{.fract=0.5h, .exp=1};
+ return;
+}
+
+)");
+}
+
+TEST_F(MslGeneratorImplTest, Const_Frexp_Vector_f32) {
+ WrapInFunction(Decl(Let("v", Call("frexp", vec3<f32>()))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec3_f32 {
+ float3 fract;
+ int3 exp;
+};
+kernel void test_function() {
+ frexp_result_vec3_f32 const v = frexp_result_vec3_f32{};
+ return;
+}
+
+)");
+}
+
+TEST_F(MslGeneratorImplTest, Const_Frexp_Vector_f16) {
+ Enable(ast::Extension::kF16);
+
+ WrapInFunction(Decl(Let("v", Call("frexp", vec3<f16>()))));
+
+ GeneratorImpl& gen = SanitizeAndBuild();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+
+using namespace metal;
+
+struct frexp_result_vec3_f16 {
+ half3 fract;
+ int3 exp;
+};
+kernel void test_function() {
+ frexp_result_vec3_f16 const v = frexp_result_vec3_f16{};
return;
}
@@ -751,19 +847,8 @@
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
using namespace metal;
-
-struct frexp_result {
- float fract;
- int exp;
-};
-frexp_result tint_frexp(float param_0) {
- frexp_result result;
- result.fract = frexp(param_0, result.exp);
- return result;
-}
-
kernel void test_function() {
- float const tint_symbol = tint_frexp(1.0f).fract;
+ float const tint_symbol = 0.5f;
return;
}
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 9b1e077..c5e4a38 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -3955,11 +3955,7 @@
if (matrix_type) {
push_annot(spv::Op::OpMemberDecorate,
{Operand(struct_id), Operand(idx), U32Operand(SpvDecorationColMajor)});
- if (!matrix_type->type()->Is<sem::F32>()) {
- error_ = "matrix scalar element type must be f32";
- return 0;
- }
- const uint32_t scalar_elem_size = 4;
+ const uint32_t scalar_elem_size = matrix_type->type()->Size();
const uint32_t effective_row_count = (matrix_type->rows() == 2) ? 2 : 4;
push_annot(spv::Op::OpMemberDecorate,
{Operand(struct_id), Operand(idx), U32Operand(SpvDecorationMatrixStride),
diff --git a/src/tint/writer/spirv/builder_builtin_test.cc b/src/tint/writer/spirv/builder_builtin_test.cc
index c0995e8..caa7d9c 100644
--- a/src/tint/writer/spirv/builder_builtin_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_test.cc
@@ -1653,7 +1653,7 @@
OpExecutionMode %3 OriginUpperLeft
OpName %3 "a_func"
OpName %10 "vec"
-OpName %14 "__modf_result_vec2"
+OpName %14 "__modf_result_vec2_f32"
OpMemberName %14 0 "fract"
OpMemberName %14 1 "whole"
OpMemberDecorate %14 0 Offset 0
@@ -1760,7 +1760,7 @@
OpEntryPoint Fragment %3 "a_func"
OpExecutionMode %3 OriginUpperLeft
OpName %3 "a_func"
-OpName %6 "__modf_result_vec2"
+OpName %6 "__modf_result_vec2_f32"
OpMemberName %6 0 "fract"
OpMemberName %6 1 "whole"
OpMemberDecorate %6 0 Offset 0
@@ -1834,7 +1834,7 @@
Validate(b);
}
-TEST_F(BuiltinBuilderTest, Call_Frexp_f32) {
+TEST_F(BuiltinBuilderTest, Runtime_Call_Frexp_f32) {
auto* vec = Var("vec", vec2<f32>(1_f, 2_f));
auto* expr = Call("frexp", vec);
Func("a_func", utils::Empty, ty.void_(),
@@ -1857,7 +1857,7 @@
OpExecutionMode %3 OriginUpperLeft
OpName %3 "a_func"
OpName %10 "vec"
-OpName %14 "__frexp_result_vec2"
+OpName %14 "__frexp_result_vec2_f32"
OpMemberName %14 0 "fract"
OpMemberName %14 1 "exp"
OpMemberDecorate %14 0 Offset 0
@@ -1888,7 +1888,7 @@
Validate(b);
}
-TEST_F(BuiltinBuilderTest, Call_Frexp_f16) {
+TEST_F(BuiltinBuilderTest, Runtime_Call_Frexp_f16) {
Enable(ast::Extension::kF16);
auto* vec = Var("vec", vec2<f16>(1_h, 2_h));
@@ -1948,15 +1948,10 @@
Validate(b);
}
-// TODO(crbug.com/tint/1757): Remove once deprecation period for `frexp().sig` is over
-TEST_F(BuiltinBuilderTest, Frexp_Sig_Deprecation) {
- WrapInFunction(MemberAccessor(Call("frexp", 1_f), "sig"));
-
- auto* vec = Var("vec", vec2<f32>(1_f, 2_f));
+TEST_F(BuiltinBuilderTest, Const_Call_Frexp_f32) {
Func("a_func", utils::Empty, ty.void_(),
utils::Vector{
- Decl(vec),
- Decl(Let("s", MemberAccessor(Call("frexp", vec), "sig"))),
+ CallStmt(Call("frexp", vec2<f32>(1_f, 2_f))),
},
utils::Vector{
Stage(ast::PipelineStage::kFragment),
@@ -1967,51 +1962,134 @@
ASSERT_TRUE(b.Build()) << b.error();
auto got = DumpBuilder(b);
auto* expect = R"(OpCapability Shader
-%9 = OpExtInstImport "GLSL.std.450"
+%11 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
-OpEntryPoint GLCompute %3 "test_function"
-OpEntryPoint Fragment %12 "a_func"
-OpExecutionMode %3 LocalSize 1 1 1
-OpExecutionMode %12 OriginUpperLeft
-OpName %3 "test_function"
-OpName %6 "__frexp_result"
+OpEntryPoint Fragment %3 "a_func"
+OpExecutionMode %3 OriginUpperLeft
+OpName %3 "a_func"
+OpName %6 "__frexp_result_vec2_f32"
OpMemberName %6 0 "fract"
OpMemberName %6 1 "exp"
-OpName %12 "a_func"
-OpName %17 "vec"
-OpName %21 "__frexp_result_vec2"
-OpMemberName %21 0 "fract"
-OpMemberName %21 1 "exp"
OpMemberDecorate %6 0 Offset 0
-OpMemberDecorate %6 1 Offset 4
-OpMemberDecorate %21 0 Offset 0
-OpMemberDecorate %21 1 Offset 8
+OpMemberDecorate %6 1 Offset 8
%2 = OpTypeVoid
%1 = OpTypeFunction %2
-%7 = OpTypeFloat 32
-%8 = OpTypeInt 32 1
-%6 = OpTypeStruct %7 %8
-%10 = OpConstant %7 1
-%14 = OpTypeVector %7 2
-%15 = OpConstant %7 2
-%16 = OpConstantComposite %14 %10 %15
-%18 = OpTypePointer Function %14
-%19 = OpConstantNull %14
-%22 = OpTypeVector %8 2
-%21 = OpTypeStruct %14 %22
+%8 = OpTypeFloat 32
+%7 = OpTypeVector %8 2
+%10 = OpTypeInt 32 1
+%9 = OpTypeVector %10 2
+%6 = OpTypeStruct %7 %9
+%12 = OpConstant %8 1
+%13 = OpConstant %8 2
+%14 = OpConstantComposite %7 %12 %13
%3 = OpFunction %2 None %1
%4 = OpLabel
-%5 = OpExtInst %6 %9 FrexpStruct %10
-%11 = OpCompositeExtract %7 %5 0
+%5 = OpExtInst %6 %11 FrexpStruct %14
OpReturn
OpFunctionEnd
-%12 = OpFunction %2 None %1
-%13 = OpLabel
-%17 = OpVariable %18 Function %19
-OpStore %17 %16
-%23 = OpLoad %14 %17
-%20 = OpExtInst %21 %9 FrexpStruct %23
-%24 = OpCompositeExtract %14 %20 0
+)";
+ EXPECT_EQ(expect, got);
+
+ Validate(b);
+}
+
+TEST_F(BuiltinBuilderTest, Const_Call_Frexp_f16) {
+ Enable(ast::Extension::kF16);
+
+ Func("a_func", utils::Empty, ty.void_(),
+ utils::Vector{
+ CallStmt(Call("frexp", vec2<f16>(1_h, 2_h))),
+ },
+ utils::Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ spirv::Builder& b = Build();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+ auto got = DumpBuilder(b);
+ auto* expect = R"(OpCapability Shader
+OpCapability Float16
+OpCapability UniformAndStorageBuffer16BitAccess
+OpCapability StorageBuffer16BitAccess
+OpCapability StorageInputOutput16
+%11 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %3 "a_func"
+OpExecutionMode %3 OriginUpperLeft
+OpName %3 "a_func"
+OpName %6 "__frexp_result_vec2_f16"
+OpMemberName %6 0 "fract"
+OpMemberName %6 1 "exp"
+OpMemberDecorate %6 0 Offset 0
+OpMemberDecorate %6 1 Offset 8
+%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%8 = OpTypeFloat 16
+%7 = OpTypeVector %8 2
+%10 = OpTypeInt 32 1
+%9 = OpTypeVector %10 2
+%6 = OpTypeStruct %7 %9
+%12 = OpConstant %8 0x1p+0
+%13 = OpConstant %8 0x1p+1
+%14 = OpConstantComposite %7 %12 %13
+%3 = OpFunction %2 None %1
+%4 = OpLabel
+%5 = OpExtInst %6 %11 FrexpStruct %14
+OpReturn
+OpFunctionEnd
+)";
+ EXPECT_EQ(expect, got);
+
+ Validate(b);
+}
+
+// TODO(crbug.com/tint/1757): Remove once deprecation period for `frexp().sig` is over
+TEST_F(BuiltinBuilderTest, Frexp_Sig_Deprecation) {
+ Func("a_func", utils::Empty, ty.void_(),
+ utils::Vector{
+ Decl(Var("vec", vec2<f32>(1_f, 2_f))),
+ Decl(Let("s", MemberAccessor(Call("frexp", "vec"), "sig"))),
+ },
+ utils::Vector{
+ Stage(ast::PipelineStage::kFragment),
+ });
+
+ spirv::Builder& b = Build();
+
+ ASSERT_TRUE(b.Build()) << b.error();
+ auto got = DumpBuilder(b);
+ auto* expect = R"(OpCapability Shader
+%17 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %3 "a_func"
+OpExecutionMode %3 OriginUpperLeft
+OpName %3 "a_func"
+OpName %10 "vec"
+OpName %14 "__frexp_result_vec2_f32"
+OpMemberName %14 0 "fract"
+OpMemberName %14 1 "exp"
+OpMemberDecorate %14 0 Offset 0
+OpMemberDecorate %14 1 Offset 8
+%2 = OpTypeVoid
+%1 = OpTypeFunction %2
+%6 = OpTypeFloat 32
+%5 = OpTypeVector %6 2
+%7 = OpConstant %6 1
+%8 = OpConstant %6 2
+%9 = OpConstantComposite %5 %7 %8
+%11 = OpTypePointer Function %5
+%12 = OpConstantNull %5
+%16 = OpTypeInt 32 1
+%15 = OpTypeVector %16 2
+%14 = OpTypeStruct %5 %15
+%3 = OpFunction %2 None %1
+%4 = OpLabel
+%10 = OpVariable %11 Function %12
+OpStore %10 %9
+%18 = OpLoad %5 %10
+%13 = OpExtInst %14 %17 FrexpStruct %18
+%19 = OpCompositeExtract %5 %13 0
OpReturn
OpFunctionEnd
)";
diff --git a/src/tint/writer/spirv/builder_type_test.cc b/src/tint/writer/spirv/builder_type_test.cc
index a17dcb5..4377c42 100644
--- a/src/tint/writer/spirv/builder_type_test.cc
+++ b/src/tint/writer/spirv/builder_type_test.cc
@@ -317,7 +317,9 @@
}
TEST_F(BuilderTest_Type, GenerateStruct) {
- auto* s = Structure("my_struct", utils::Vector{Member("a", ty.f32())});
+ Enable(ast::Extension::kF16);
+
+ auto* s = Structure("my_struct", utils::Vector{Member("a", ty.f32()), Member("b", ty.f16())});
spirv::Builder& b = Build();
@@ -326,17 +328,23 @@
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeStruct %2
+%3 = OpTypeFloat 16
+%1 = OpTypeStruct %2 %3
)");
EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "my_struct"
OpMemberName %1 0 "a"
+OpMemberName %1 1 "b"
)");
}
TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers) {
+ Enable(ast::Extension::kF16);
+
auto* s = Structure("S", utils::Vector{
Member("a", ty.f32()),
Member("b", ty.f32(), utils::Vector{MemberAlign(8_i)}),
+ Member("c", ty.f16(), utils::Vector{MemberAlign(8_u)}),
+ Member("d", ty.f16()),
});
spirv::Builder& b = Build();
@@ -346,23 +354,34 @@
EXPECT_EQ(id, 1u);
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
-%1 = OpTypeStruct %2 %2
+%3 = OpTypeFloat 16
+%1 = OpTypeStruct %2 %2 %3 %3
)");
EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "S"
OpMemberName %1 0 "a"
OpMemberName %1 1 "b"
+OpMemberName %1 2 "c"
+OpMemberName %1 3 "d"
)");
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpMemberDecorate %1 0 Offset 0
OpMemberDecorate %1 1 Offset 8
+OpMemberDecorate %1 2 Offset 16
+OpMemberDecorate %1 3 Offset 18
)");
}
-TEST_F(BuilderTest_Type, GenerateStruct_NonLayout_Matrix) {
- auto* s = Structure("S", utils::Vector{
- Member("a", ty.mat2x2<f32>()),
- Member("b", ty.mat2x3<f32>()),
- Member("c", ty.mat4x4<f32>()),
- });
+TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers_Matrix) {
+ Enable(ast::Extension::kF16);
+
+ auto* s =
+ Structure("S", utils::Vector{
+ Member("mat2x2_f32", ty.mat2x2<f32>()),
+ Member("mat2x3_f32", ty.mat2x3<f32>(), utils::Vector{MemberAlign(64_i)}),
+ Member("mat4x4_f32", ty.mat4x4<f32>()),
+ Member("mat2x2_f16", ty.mat2x2<f16>(), utils::Vector{MemberAlign(32_i)}),
+ Member("mat2x3_f16", ty.mat2x3<f16>()),
+ Member("mat4x4_f16", ty.mat4x4<f16>(), utils::Vector{MemberAlign(64_i)}),
+ });
spirv::Builder& b = Build();
@@ -377,78 +396,63 @@
%5 = OpTypeMatrix %6 2
%8 = OpTypeVector %4 4
%7 = OpTypeMatrix %8 4
-%1 = OpTypeStruct %2 %5 %7
+%11 = OpTypeFloat 16
+%10 = OpTypeVector %11 2
+%9 = OpTypeMatrix %10 2
+%13 = OpTypeVector %11 3
+%12 = OpTypeMatrix %13 2
+%15 = OpTypeVector %11 4
+%14 = OpTypeMatrix %15 4
+%1 = OpTypeStruct %2 %5 %7 %9 %12 %14
)");
EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "S"
-OpMemberName %1 0 "a"
-OpMemberName %1 1 "b"
-OpMemberName %1 2 "c"
+OpMemberName %1 0 "mat2x2_f32"
+OpMemberName %1 1 "mat2x3_f32"
+OpMemberName %1 2 "mat4x4_f32"
+OpMemberName %1 3 "mat2x2_f16"
+OpMemberName %1 4 "mat2x3_f16"
+OpMemberName %1 5 "mat4x4_f16"
)");
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpMemberDecorate %1 0 Offset 0
OpMemberDecorate %1 0 ColMajor
OpMemberDecorate %1 0 MatrixStride 8
-OpMemberDecorate %1 1 Offset 16
+OpMemberDecorate %1 1 Offset 64
OpMemberDecorate %1 1 ColMajor
OpMemberDecorate %1 1 MatrixStride 16
-OpMemberDecorate %1 2 Offset 48
+OpMemberDecorate %1 2 Offset 96
OpMemberDecorate %1 2 ColMajor
OpMemberDecorate %1 2 MatrixStride 16
+OpMemberDecorate %1 3 Offset 160
+OpMemberDecorate %1 3 ColMajor
+OpMemberDecorate %1 3 MatrixStride 4
+OpMemberDecorate %1 4 Offset 168
+OpMemberDecorate %1 4 ColMajor
+OpMemberDecorate %1 4 MatrixStride 8
+OpMemberDecorate %1 5 Offset 192
+OpMemberDecorate %1 5 ColMajor
+OpMemberDecorate %1 5 MatrixStride 8
)");
}
-TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers_LayoutMatrix) {
- // We have to infer layout for matrix when it also has an offset.
- auto* s = Structure("S", utils::Vector{
- Member("a", ty.mat2x2<f32>()),
- Member("b", ty.mat2x3<f32>()),
- Member("c", ty.mat4x4<f32>()),
- });
+TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers_ArraysOfMatrix) {
+ Enable(ast::Extension::kF16);
- spirv::Builder& b = Build();
-
- auto id = b.GenerateTypeIfNeeded(program->TypeOf(s));
- ASSERT_FALSE(b.has_error()) << b.error();
- EXPECT_EQ(id, 1u);
-
- EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
-%3 = OpTypeVector %4 2
-%2 = OpTypeMatrix %3 2
-%6 = OpTypeVector %4 3
-%5 = OpTypeMatrix %6 2
-%8 = OpTypeVector %4 4
-%7 = OpTypeMatrix %8 4
-%1 = OpTypeStruct %2 %5 %7
-)");
- EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "S"
-OpMemberName %1 0 "a"
-OpMemberName %1 1 "b"
-OpMemberName %1 2 "c"
-)");
- EXPECT_EQ(DumpInstructions(b.annots()), R"(OpMemberDecorate %1 0 Offset 0
-OpMemberDecorate %1 0 ColMajor
-OpMemberDecorate %1 0 MatrixStride 8
-OpMemberDecorate %1 1 Offset 16
-OpMemberDecorate %1 1 ColMajor
-OpMemberDecorate %1 1 MatrixStride 16
-OpMemberDecorate %1 2 Offset 48
-OpMemberDecorate %1 2 ColMajor
-OpMemberDecorate %1 2 MatrixStride 16
-)");
-}
-
-TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers_LayoutArraysOfMatrix) {
- // We have to infer layout for matrix when it also has an offset.
- // The decoration goes on the struct member, even if the matrix is buried
- // in levels of arrays.
- auto* arr_mat2x2 = ty.array(ty.mat2x2<f32>(), 1_u); // Singly nested array
- auto* arr_arr_mat2x3 = ty.array(ty.mat2x3<f32>(), 1_u); // Doubly nested array
+ auto* arr_mat2x2_f32 = ty.array(ty.mat2x2<f32>(), 1_u); // Singly nested array
+ auto* arr_mat2x2_f16 = ty.array(ty.mat2x2<f16>(), 1_u); // Singly nested array
+ auto* arr_arr_mat2x3_f32 =
+ ty.array(ty.array(ty.mat2x3<f32>(), 1_u), 2_u); // Doubly nested array
+ auto* arr_arr_mat2x3_f16 =
+ ty.array(ty.array(ty.mat2x3<f16>(), 1_u), 2_u); // Doubly nested array
auto* rtarr_mat4x4 = ty.array(ty.mat4x4<f32>()); // Runtime array
- auto* s = Structure("S", utils::Vector{
- Member("a", arr_mat2x2),
- Member("b", arr_arr_mat2x3),
- Member("c", rtarr_mat4x4),
- });
+ auto* s = Structure(
+ "S", utils::Vector{
+ Member("arr_mat2x2_f32", arr_mat2x2_f32),
+ Member("arr_mat2x2_f16", arr_mat2x2_f16, utils::Vector{MemberAlign(64_i)}),
+ Member("arr_arr_mat2x3_f32", arr_arr_mat2x3_f32, utils::Vector{MemberAlign(64_i)}),
+ Member("arr_arr_mat2x3_f16", arr_arr_mat2x3_f16),
+ Member("rtarr_mat4x4", rtarr_mat4x4),
+ });
spirv::Builder& b = Build();
@@ -462,31 +466,53 @@
%6 = OpTypeInt 32 0
%7 = OpConstant %6 1
%2 = OpTypeArray %3 %7
-%10 = OpTypeVector %5 3
+%11 = OpTypeFloat 16
+%10 = OpTypeVector %11 2
%9 = OpTypeMatrix %10 2
%8 = OpTypeArray %9 %7
-%13 = OpTypeVector %5 4
-%12 = OpTypeMatrix %13 4
-%11 = OpTypeRuntimeArray %12
-%1 = OpTypeStruct %2 %8 %11
+%15 = OpTypeVector %5 3
+%14 = OpTypeMatrix %15 2
+%13 = OpTypeArray %14 %7
+%16 = OpConstant %6 2
+%12 = OpTypeArray %13 %16
+%20 = OpTypeVector %11 3
+%19 = OpTypeMatrix %20 2
+%18 = OpTypeArray %19 %7
+%17 = OpTypeArray %18 %16
+%23 = OpTypeVector %5 4
+%22 = OpTypeMatrix %23 4
+%21 = OpTypeRuntimeArray %22
+%1 = OpTypeStruct %2 %8 %12 %17 %21
)");
EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "S"
-OpMemberName %1 0 "a"
-OpMemberName %1 1 "b"
-OpMemberName %1 2 "c"
+OpMemberName %1 0 "arr_mat2x2_f32"
+OpMemberName %1 1 "arr_mat2x2_f16"
+OpMemberName %1 2 "arr_arr_mat2x3_f32"
+OpMemberName %1 3 "arr_arr_mat2x3_f16"
+OpMemberName %1 4 "rtarr_mat4x4"
)");
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpMemberDecorate %1 0 Offset 0
OpMemberDecorate %1 0 ColMajor
OpMemberDecorate %1 0 MatrixStride 8
OpDecorate %2 ArrayStride 16
-OpMemberDecorate %1 1 Offset 16
+OpMemberDecorate %1 1 Offset 64
OpMemberDecorate %1 1 ColMajor
-OpMemberDecorate %1 1 MatrixStride 16
-OpDecorate %8 ArrayStride 32
-OpMemberDecorate %1 2 Offset 48
+OpMemberDecorate %1 1 MatrixStride 4
+OpDecorate %8 ArrayStride 8
+OpMemberDecorate %1 2 Offset 128
OpMemberDecorate %1 2 ColMajor
OpMemberDecorate %1 2 MatrixStride 16
-OpDecorate %11 ArrayStride 64
+OpDecorate %13 ArrayStride 32
+OpDecorate %12 ArrayStride 32
+OpMemberDecorate %1 3 Offset 192
+OpMemberDecorate %1 3 ColMajor
+OpMemberDecorate %1 3 MatrixStride 8
+OpDecorate %18 ArrayStride 16
+OpDecorate %17 ArrayStride 16
+OpMemberDecorate %1 4 Offset 224
+OpMemberDecorate %1 4 ColMajor
+OpMemberDecorate %1 4 MatrixStride 16
+OpDecorate %21 ArrayStride 64
)");
}