mirror of
				https://github.com/encounter/dawn-cmake.git
				synced 2025-10-27 12:10:29 +00:00 
			
		
		
		
	tint/writer/msl: Generate an array<T,N> helper
And remove the WrapArraysInStructs transform. Wrapping arrays in structures becomes troublesome for `const` arrays, as currently WGSL does not allow `const` structures. MSL 2.0+ has a builtin array<> helper, but we're targetting MSL 1.2, so we have to emit our own. Fortunately, it can be done with a few lines of templated code. This produces significantly cleaner output. Change-Id: Ifc92ef21e09befa252a07c856c4b5afdc51cc2e4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94540 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
		
							parent
							
								
									3c054304a8
								
							
						
					
					
						commit
						f47887d207
					
				| @ -543,8 +543,6 @@ libtint_source_set("libtint_core_all_src") { | |||||||
|     "transform/vertex_pulling.h", |     "transform/vertex_pulling.h", | ||||||
|     "transform/while_to_loop.cc", |     "transform/while_to_loop.cc", | ||||||
|     "transform/while_to_loop.h", |     "transform/while_to_loop.h", | ||||||
|     "transform/wrap_arrays_in_structs.cc", |  | ||||||
|     "transform/wrap_arrays_in_structs.h", |  | ||||||
|     "transform/zero_init_workgroup_memory.cc", |     "transform/zero_init_workgroup_memory.cc", | ||||||
|     "transform/zero_init_workgroup_memory.h", |     "transform/zero_init_workgroup_memory.h", | ||||||
|     "utils/bitcast.h", |     "utils/bitcast.h", | ||||||
| @ -1199,7 +1197,6 @@ if (tint_build_unittests) { | |||||||
|       "transform/vectorize_scalar_matrix_constructors_test.cc", |       "transform/vectorize_scalar_matrix_constructors_test.cc", | ||||||
|       "transform/vertex_pulling_test.cc", |       "transform/vertex_pulling_test.cc", | ||||||
|       "transform/while_to_loop_test.cc", |       "transform/while_to_loop_test.cc", | ||||||
|       "transform/wrap_arrays_in_structs_test.cc", |  | ||||||
|       "transform/zero_init_workgroup_memory_test.cc", |       "transform/zero_init_workgroup_memory_test.cc", | ||||||
|     ] |     ] | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -466,8 +466,6 @@ set(TINT_LIB_SRCS | |||||||
|   transform/vertex_pulling.h |   transform/vertex_pulling.h | ||||||
|   transform/while_to_loop.cc |   transform/while_to_loop.cc | ||||||
|   transform/while_to_loop.h |   transform/while_to_loop.h | ||||||
|   transform/wrap_arrays_in_structs.cc |  | ||||||
|   transform/wrap_arrays_in_structs.h |  | ||||||
|   transform/zero_init_workgroup_memory.cc |   transform/zero_init_workgroup_memory.cc | ||||||
|   transform/zero_init_workgroup_memory.h |   transform/zero_init_workgroup_memory.h | ||||||
|   utils/bitcast.h |   utils/bitcast.h | ||||||
| @ -1121,7 +1119,6 @@ if(TINT_BUILD_TESTS) | |||||||
|       transform/vectorize_scalar_matrix_constructors_test.cc |       transform/vectorize_scalar_matrix_constructors_test.cc | ||||||
|       transform/vertex_pulling_test.cc |       transform/vertex_pulling_test.cc | ||||||
|       transform/while_to_loop_test.cc |       transform/while_to_loop_test.cc | ||||||
|       transform/wrap_arrays_in_structs_test.cc |  | ||||||
|       transform/zero_init_workgroup_memory_test.cc |       transform/zero_init_workgroup_memory_test.cc | ||||||
|       transform/utils/get_insertion_point_test.cc |       transform/utils/get_insertion_point_test.cc | ||||||
|       transform/utils/hoist_to_decl_before_test.cc |       transform/utils/hoist_to_decl_before_test.cc | ||||||
|  | |||||||
| @ -1,158 +0,0 @@ | |||||||
| // Copyright 2021 The Tint Authors.
 |  | ||||||
| //
 |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 |  | ||||||
| // you may not use this file except in compliance with the License.
 |  | ||||||
| // You may obtain a copy of the License at
 |  | ||||||
| //
 |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| //
 |  | ||||||
| // Unless required by applicable law or agreed to in writing, software
 |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  | ||||||
| // See the License for the specific language governing permissions and
 |  | ||||||
| // limitations under the License.
 |  | ||||||
| 
 |  | ||||||
| #include "src/tint/transform/wrap_arrays_in_structs.h" |  | ||||||
| 
 |  | ||||||
| #include <utility> |  | ||||||
| 
 |  | ||||||
| #include "src/tint/program_builder.h" |  | ||||||
| #include "src/tint/sem/array.h" |  | ||||||
| #include "src/tint/sem/call.h" |  | ||||||
| #include "src/tint/sem/expression.h" |  | ||||||
| #include "src/tint/sem/type_constructor.h" |  | ||||||
| #include "src/tint/utils/map.h" |  | ||||||
| #include "src/tint/utils/transform.h" |  | ||||||
| 
 |  | ||||||
| TINT_INSTANTIATE_TYPEINFO(tint::transform::WrapArraysInStructs); |  | ||||||
| 
 |  | ||||||
| namespace tint::transform { |  | ||||||
| 
 |  | ||||||
| WrapArraysInStructs::WrappedArrayInfo::WrappedArrayInfo() = default; |  | ||||||
| WrapArraysInStructs::WrappedArrayInfo::WrappedArrayInfo(const WrappedArrayInfo&) = default; |  | ||||||
| WrapArraysInStructs::WrappedArrayInfo::~WrappedArrayInfo() = default; |  | ||||||
| 
 |  | ||||||
| WrapArraysInStructs::WrapArraysInStructs() = default; |  | ||||||
| 
 |  | ||||||
| WrapArraysInStructs::~WrapArraysInStructs() = default; |  | ||||||
| 
 |  | ||||||
| bool WrapArraysInStructs::ShouldRun(const Program* program, const DataMap&) const { |  | ||||||
|     for (auto* node : program->ASTNodes().Objects()) { |  | ||||||
|         if (program->Sem().Get<sem::Array>(node->As<ast::Type>())) { |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void WrapArraysInStructs::Run(CloneContext& ctx, const DataMap&, DataMap&) const { |  | ||||||
|     auto& sem = ctx.src->Sem(); |  | ||||||
| 
 |  | ||||||
|     std::unordered_map<const sem::Array*, WrappedArrayInfo> wrapped_arrays; |  | ||||||
|     auto wrapper = [&](const sem::Array* array) { return WrapArray(ctx, wrapped_arrays, array); }; |  | ||||||
|     auto wrapper_typename = [&](const sem::Array* arr) -> ast::TypeName* { |  | ||||||
|         auto info = wrapper(arr); |  | ||||||
|         return info ? ctx.dst->create<ast::TypeName>(info.wrapper_name) : nullptr; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     // Replace all array types with their corresponding wrapper
 |  | ||||||
|     ctx.ReplaceAll([&](const ast::Type* ast_type) -> const ast::Type* { |  | ||||||
|         auto* type = ctx.src->TypeOf(ast_type); |  | ||||||
|         if (auto* array = type->UnwrapRef()->As<sem::Array>()) { |  | ||||||
|             return wrapper_typename(array); |  | ||||||
|         } |  | ||||||
|         return nullptr; |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // Fix up index accessors so `a[1]` becomes `a.arr[1]`
 |  | ||||||
|     ctx.ReplaceAll( |  | ||||||
|         [&](const ast::IndexAccessorExpression* accessor) -> const ast::IndexAccessorExpression* { |  | ||||||
|             if (auto* array = |  | ||||||
|                     ::tint::As<sem::Array>(sem.Get(accessor->object)->Type()->UnwrapRef())) { |  | ||||||
|                 if (wrapper(array)) { |  | ||||||
|                     // Array is wrapped in a structure. Emit a member accessor to get
 |  | ||||||
|                     // to the actual array.
 |  | ||||||
|                     auto* arr = ctx.Clone(accessor->object); |  | ||||||
|                     auto* idx = ctx.Clone(accessor->index); |  | ||||||
|                     auto* unwrapped = ctx.dst->MemberAccessor(arr, "arr"); |  | ||||||
|                     return ctx.dst->IndexAccessor(accessor->source, unwrapped, idx); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return nullptr; |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|     // Fix up array constructors so `A(1,2)` becomes `tint_array_wrapper(A(1,2))`
 |  | ||||||
|     ctx.ReplaceAll([&](const ast::CallExpression* expr) -> const ast::Expression* { |  | ||||||
|         if (auto* call = sem.Get(expr)->UnwrapMaterialize()->As<sem::Call>()) { |  | ||||||
|             if (auto* ctor = call->Target()->As<sem::TypeConstructor>()) { |  | ||||||
|                 if (auto* array = ctor->ReturnType()->As<sem::Array>()) { |  | ||||||
|                     if (auto w = wrapper(array)) { |  | ||||||
|                         // Wrap the array type constructor with another constructor for
 |  | ||||||
|                         // the wrapper
 |  | ||||||
|                         auto* wrapped_array_ty = ctx.dst->ty.type_name(w.wrapper_name); |  | ||||||
|                         auto* array_ty = w.array_type(ctx); |  | ||||||
|                         auto args = utils::Transform(call->Arguments(), |  | ||||||
|                                                      [&](const tint::sem::Expression* s) { |  | ||||||
|                                                          return ctx.Clone(s->Declaration()); |  | ||||||
|                                                      }); |  | ||||||
|                         auto* arr_ctor = ctx.dst->Construct(array_ty, args); |  | ||||||
|                         return ctx.dst->Construct(wrapped_array_ty, arr_ctor); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return nullptr; |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     ctx.Clone(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| WrapArraysInStructs::WrappedArrayInfo WrapArraysInStructs::WrapArray( |  | ||||||
|     CloneContext& ctx, |  | ||||||
|     std::unordered_map<const sem::Array*, WrappedArrayInfo>& wrapped_arrays, |  | ||||||
|     const sem::Array* array) const { |  | ||||||
|     if (array->IsRuntimeSized()) { |  | ||||||
|         return {};  // We don't want to wrap runtime sized arrays
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return utils::GetOrCreate(wrapped_arrays, array, [&] { |  | ||||||
|         WrappedArrayInfo info; |  | ||||||
| 
 |  | ||||||
|         // Generate a unique name for the array wrapper
 |  | ||||||
|         info.wrapper_name = ctx.dst->Symbols().New("tint_array_wrapper"); |  | ||||||
| 
 |  | ||||||
|         // Examine the element type. Is it also an array?
 |  | ||||||
|         std::function<const ast::Type*(CloneContext&)> el_type; |  | ||||||
|         if (auto* el_array = array->ElemType()->As<sem::Array>()) { |  | ||||||
|             // Array of array - call WrapArray() on the element type
 |  | ||||||
|             if (auto el = WrapArray(ctx, wrapped_arrays, el_array)) { |  | ||||||
|                 el_type = [=](CloneContext& c) { |  | ||||||
|                     return c.dst->create<ast::TypeName>(el.wrapper_name); |  | ||||||
|                 }; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // If the element wasn't an array, just create the typical AST type for it
 |  | ||||||
|         if (!el_type) { |  | ||||||
|             el_type = [=](CloneContext& c) { return CreateASTTypeFor(c, array->ElemType()); }; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Construct the single structure field type
 |  | ||||||
|         info.array_type = [=](CloneContext& c) { |  | ||||||
|             ast::AttributeList attrs; |  | ||||||
|             if (!array->IsStrideImplicit()) { |  | ||||||
|                 attrs.emplace_back(c.dst->create<ast::StrideAttribute>(array->Stride())); |  | ||||||
|             } |  | ||||||
|             return c.dst->ty.array(el_type(c), u32(array->Count()), std::move(attrs)); |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         // Structure() will create and append the ast::Struct to the
 |  | ||||||
|         // global declarations of `ctx.dst`. As we haven't finished building the
 |  | ||||||
|         // current module-scope statement or function, this will be placed
 |  | ||||||
|         // immediately before the usage.
 |  | ||||||
|         ctx.dst->Structure(info.wrapper_name, {ctx.dst->Member("arr", info.array_type(ctx))}); |  | ||||||
|         return info; |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| }  // namespace tint::transform
 |  | ||||||
| @ -1,88 +0,0 @@ | |||||||
| // Copyright 2021 The Tint Authors.
 |  | ||||||
| //
 |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 |  | ||||||
| // you may not use this file except in compliance with the License.
 |  | ||||||
| // You may obtain a copy of the License at
 |  | ||||||
| //
 |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| //
 |  | ||||||
| // Unless required by applicable law or agreed to in writing, software
 |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  | ||||||
| // See the License for the specific language governing permissions and
 |  | ||||||
| // limitations under the License.
 |  | ||||||
| 
 |  | ||||||
| #ifndef SRC_TINT_TRANSFORM_WRAP_ARRAYS_IN_STRUCTS_H_ |  | ||||||
| #define SRC_TINT_TRANSFORM_WRAP_ARRAYS_IN_STRUCTS_H_ |  | ||||||
| 
 |  | ||||||
| #include <string> |  | ||||||
| #include <unordered_map> |  | ||||||
| 
 |  | ||||||
| #include "src/tint/transform/transform.h" |  | ||||||
| 
 |  | ||||||
| // Forward declarations
 |  | ||||||
| namespace tint::ast { |  | ||||||
| class Type; |  | ||||||
| }  // namespace tint::ast
 |  | ||||||
| 
 |  | ||||||
| namespace tint::transform { |  | ||||||
| 
 |  | ||||||
| /// WrapArraysInStructs is a transform that replaces all array types with a
 |  | ||||||
| /// structure holding a single field of that array type.
 |  | ||||||
| /// Array index expressions and constructors are also adjusted to deal with this
 |  | ||||||
| /// wrapping.
 |  | ||||||
| /// This transform helps with backends that cannot directly return arrays or use
 |  | ||||||
| /// them as parameters.
 |  | ||||||
| class WrapArraysInStructs : public Castable<WrapArraysInStructs, Transform> { |  | ||||||
|   public: |  | ||||||
|     /// Constructor
 |  | ||||||
|     WrapArraysInStructs(); |  | ||||||
| 
 |  | ||||||
|     /// Destructor
 |  | ||||||
|     ~WrapArraysInStructs() override; |  | ||||||
| 
 |  | ||||||
|     /// @param program the program to inspect
 |  | ||||||
|     /// @param data optional extra transform-specific input data
 |  | ||||||
|     /// @returns true if this transform should be run for the given program
 |  | ||||||
|     bool ShouldRun(const Program* program, const DataMap& data = {}) const override; |  | ||||||
| 
 |  | ||||||
|   protected: |  | ||||||
|     /// Runs the transform using the CloneContext built for transforming a
 |  | ||||||
|     /// program. Run() is responsible for calling Clone() on the CloneContext.
 |  | ||||||
|     /// @param ctx the CloneContext primed with the input program and
 |  | ||||||
|     /// ProgramBuilder
 |  | ||||||
|     /// @param inputs optional extra transform-specific input data
 |  | ||||||
|     /// @param outputs optional extra transform-specific output data
 |  | ||||||
|     void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) const override; |  | ||||||
| 
 |  | ||||||
|   private: |  | ||||||
|     struct WrappedArrayInfo { |  | ||||||
|         WrappedArrayInfo(); |  | ||||||
|         WrappedArrayInfo(const WrappedArrayInfo&); |  | ||||||
|         ~WrappedArrayInfo(); |  | ||||||
| 
 |  | ||||||
|         Symbol wrapper_name; |  | ||||||
|         std::function<const ast::Type*(CloneContext&)> array_type; |  | ||||||
| 
 |  | ||||||
|         operator bool() { return wrapper_name.IsValid(); } |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     /// WrapArray wraps the fixed-size array type in a new structure (if it hasn't
 |  | ||||||
|     /// already been wrapped). WrapArray will recursively wrap arrays-of-arrays.
 |  | ||||||
|     /// The new structure will be added to module-scope type declarations of
 |  | ||||||
|     /// `ctx.dst`.
 |  | ||||||
|     /// @param ctx the CloneContext
 |  | ||||||
|     /// @param wrapped_arrays a map of src array type to the wrapped structure
 |  | ||||||
|     /// name
 |  | ||||||
|     /// @param array the array type
 |  | ||||||
|     /// @return the name of the structure that wraps the array, or an invalid
 |  | ||||||
|     /// Symbol if this array should not be wrapped
 |  | ||||||
|     WrappedArrayInfo WrapArray( |  | ||||||
|         CloneContext& ctx, |  | ||||||
|         std::unordered_map<const sem::Array*, WrappedArrayInfo>& wrapped_arrays, |  | ||||||
|         const sem::Array* array) const; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| }  // namespace tint::transform
 |  | ||||||
| 
 |  | ||||||
| #endif  // SRC_TINT_TRANSFORM_WRAP_ARRAYS_IN_STRUCTS_H_
 |  | ||||||
| @ -1,422 +0,0 @@ | |||||||
| // Copyright 2021 The Tint Authors.
 |  | ||||||
| //
 |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 |  | ||||||
| // you may not use this file except in compliance with the License.
 |  | ||||||
| // You may obtain a copy of the License at
 |  | ||||||
| //
 |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| //
 |  | ||||||
| // Unless required by applicable law or agreed to in writing, software
 |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  | ||||||
| // See the License for the specific language governing permissions and
 |  | ||||||
| // limitations under the License.
 |  | ||||||
| 
 |  | ||||||
| #include "src/tint/transform/wrap_arrays_in_structs.h" |  | ||||||
| 
 |  | ||||||
| #include <memory> |  | ||||||
| #include <utility> |  | ||||||
| 
 |  | ||||||
| #include "src/tint/transform/test_helper.h" |  | ||||||
| 
 |  | ||||||
| namespace tint::transform { |  | ||||||
| namespace { |  | ||||||
| 
 |  | ||||||
| using WrapArraysInStructsTest = TransformTest; |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ShouldRunEmptyModule) { |  | ||||||
|     auto* src = R"()"; |  | ||||||
| 
 |  | ||||||
|     EXPECT_FALSE(ShouldRun<WrapArraysInStructs>(src)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ShouldRunHasArray) { |  | ||||||
|     auto* src = R"( |  | ||||||
| var<private> arr : array<i32, 4>; |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     EXPECT_TRUE(ShouldRun<WrapArraysInStructs>(src)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, EmptyModule) { |  | ||||||
|     auto* src = R"()"; |  | ||||||
|     auto* expect = src; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArrayAsGlobal) { |  | ||||||
|     auto* src = R"( |  | ||||||
| var<private> arr : array<i32, 4>; |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| var<private> arr : tint_array_wrapper; |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArrayAsFunctionVar) { |  | ||||||
|     auto* src = R"( |  | ||||||
| fn f() { |  | ||||||
|   var arr : array<i32, 4>; |  | ||||||
|   let x = arr[3]; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f() { |  | ||||||
|   var arr : tint_array_wrapper; |  | ||||||
|   let x = arr.arr[3]; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArrayAsParam) { |  | ||||||
|     auto* src = R"( |  | ||||||
| fn f(a : array<i32, 4>) -> i32 { |  | ||||||
|   return a[2]; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f(a : tint_array_wrapper) -> i32 { |  | ||||||
|   return a.arr[2]; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArrayAsReturn) { |  | ||||||
|     auto* src = R"( |  | ||||||
| fn f() -> array<i32, 4> { |  | ||||||
|   return array<i32, 4>(1, 2, 3, 4); |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f() -> tint_array_wrapper { |  | ||||||
|   return tint_array_wrapper(array<i32, 4u>(1, 2, 3, 4)); |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArrayAlias) { |  | ||||||
|     auto* src = R"( |  | ||||||
| type Inner = array<i32, 2>; |  | ||||||
| type Array = array<Inner, 2>; |  | ||||||
| 
 |  | ||||||
| fn f() { |  | ||||||
|   var arr : Array; |  | ||||||
|   arr = Array(); |  | ||||||
|   arr = Array(Inner(1, 2), Inner(3, 4)); |  | ||||||
|   let vals : Array = Array(Inner(1, 2), Inner(3, 4)); |  | ||||||
|   arr = vals; |  | ||||||
|   let x = arr[3]; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 2u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type Inner = tint_array_wrapper; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   arr : array<tint_array_wrapper, 2u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type Array = tint_array_wrapper_1; |  | ||||||
| 
 |  | ||||||
| fn f() { |  | ||||||
|   var arr : tint_array_wrapper_1; |  | ||||||
|   arr = tint_array_wrapper_1(array<tint_array_wrapper, 2u>()); |  | ||||||
|   arr = tint_array_wrapper_1(array<tint_array_wrapper, 2u>(tint_array_wrapper(array<i32, 2u>(1, 2)), tint_array_wrapper(array<i32, 2u>(3, 4)))); |  | ||||||
|   let vals : tint_array_wrapper_1 = tint_array_wrapper_1(array<tint_array_wrapper, 2u>(tint_array_wrapper(array<i32, 2u>(1, 2)), tint_array_wrapper(array<i32, 2u>(3, 4)))); |  | ||||||
|   arr = vals; |  | ||||||
|   let x = arr.arr[3]; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArrayAlias_OutOfOrder) { |  | ||||||
|     auto* src = R"( |  | ||||||
| fn f() { |  | ||||||
|   var arr : Array; |  | ||||||
|   arr = Array(); |  | ||||||
|   arr = Array(Inner(1, 2), Inner(3, 4)); |  | ||||||
|   let vals : Array = Array(Inner(1, 2), Inner(3, 4)); |  | ||||||
|   arr = vals; |  | ||||||
|   let x = arr[3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type Array = array<Inner, 2>; |  | ||||||
| type Inner = array<i32, 2>; |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   arr : array<i32, 2u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<tint_array_wrapper_1, 2u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f() { |  | ||||||
|   var arr : tint_array_wrapper; |  | ||||||
|   arr = tint_array_wrapper(array<tint_array_wrapper_1, 2u>()); |  | ||||||
|   arr = tint_array_wrapper(array<tint_array_wrapper_1, 2u>(tint_array_wrapper_1(array<i32, 2u>(1, 2)), tint_array_wrapper_1(array<i32, 2u>(3, 4)))); |  | ||||||
|   let vals : tint_array_wrapper = tint_array_wrapper(array<tint_array_wrapper_1, 2u>(tint_array_wrapper_1(array<i32, 2u>(1, 2)), tint_array_wrapper_1(array<i32, 2u>(3, 4)))); |  | ||||||
|   arr = vals; |  | ||||||
|   let x = arr.arr[3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type Array = tint_array_wrapper; |  | ||||||
| 
 |  | ||||||
| type Inner = tint_array_wrapper_1; |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArraysInStruct) { |  | ||||||
|     auto* src = R"( |  | ||||||
| struct S { |  | ||||||
|   a : array<i32, 4>, |  | ||||||
|   b : array<i32, 8>, |  | ||||||
|   c : array<i32, 4>, |  | ||||||
| }; |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   arr : array<i32, 8u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct S { |  | ||||||
|   a : tint_array_wrapper, |  | ||||||
|   b : tint_array_wrapper_1, |  | ||||||
|   c : tint_array_wrapper, |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, ArraysOfArraysInStruct) { |  | ||||||
|     auto* src = R"( |  | ||||||
| struct S { |  | ||||||
|   a : array<i32, 4>, |  | ||||||
|   b : array<array<i32, 4>, 4>, |  | ||||||
|   c : array<array<array<i32, 4>, 4>, 4>, |  | ||||||
| }; |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   arr : array<tint_array_wrapper, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   arr : array<tint_array_wrapper_1, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct S { |  | ||||||
|   a : tint_array_wrapper, |  | ||||||
|   b : tint_array_wrapper_1, |  | ||||||
|   c : tint_array_wrapper_2, |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, AccessArraysOfArraysInStruct) { |  | ||||||
|     auto* src = R"( |  | ||||||
| struct S { |  | ||||||
|   a : array<i32, 4>, |  | ||||||
|   b : array<array<i32, 4>, 4>, |  | ||||||
|   c : array<array<array<i32, 4>, 4>, 4>, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| fn f(s : S) -> i32 { |  | ||||||
|   return s.a[2] + s.b[1][2] + s.c[3][1][2]; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   arr : array<tint_array_wrapper, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   arr : array<tint_array_wrapper_1, 4u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct S { |  | ||||||
|   a : tint_array_wrapper, |  | ||||||
|   b : tint_array_wrapper_1, |  | ||||||
|   c : tint_array_wrapper_2, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f(s : S) -> i32 { |  | ||||||
|   return ((s.a.arr[2] + s.b.arr[1].arr[2]) + s.c.arr[3].arr[1].arr[2]); |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, DeclarationOrder) { |  | ||||||
|     auto* src = R"( |  | ||||||
| type T0 = i32; |  | ||||||
| 
 |  | ||||||
| type T1 = array<i32, 1>; |  | ||||||
| 
 |  | ||||||
| type T2 = i32; |  | ||||||
| 
 |  | ||||||
| fn f1(a : array<i32, 2>) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T3 = i32; |  | ||||||
| 
 |  | ||||||
| fn f2() { |  | ||||||
|   var v : array<i32, 3>; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| type T0 = i32; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 1u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T1 = tint_array_wrapper; |  | ||||||
| 
 |  | ||||||
| type T2 = i32; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   arr : array<i32, 2u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f1(a : tint_array_wrapper_1) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T3 = i32; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   arr : array<i32, 3u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f2() { |  | ||||||
|   var v : tint_array_wrapper_2; |  | ||||||
| } |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| TEST_F(WrapArraysInStructsTest, DeclarationOrder_OutOfOrder) { |  | ||||||
|     auto* src = R"( |  | ||||||
| fn f2() { |  | ||||||
|   var v : array<i32, 3>; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T3 = i32; |  | ||||||
| 
 |  | ||||||
| fn f1(a : array<i32, 2>) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T2 = i32; |  | ||||||
| 
 |  | ||||||
| type T1 = array<i32, 1>; |  | ||||||
| 
 |  | ||||||
| type T0 = i32; |  | ||||||
| )"; |  | ||||||
|     auto* expect = R"( |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   arr : array<i32, 3u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f2() { |  | ||||||
|   var v : tint_array_wrapper; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T3 = i32; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   arr : array<i32, 2u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn f1(a : tint_array_wrapper_1) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T2 = i32; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   arr : array<i32, 1u>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type T1 = tint_array_wrapper_2; |  | ||||||
| 
 |  | ||||||
| type T0 = i32; |  | ||||||
| )"; |  | ||||||
| 
 |  | ||||||
|     auto got = Run<WrapArraysInStructs>(src); |  | ||||||
| 
 |  | ||||||
|     EXPECT_EQ(expect, str(got)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| }  // namespace
 |  | ||||||
| }  // namespace tint::transform
 |  | ||||||
| @ -71,7 +71,6 @@ | |||||||
| #include "src/tint/transform/unshadow.h" | #include "src/tint/transform/unshadow.h" | ||||||
| #include "src/tint/transform/unwind_discard_functions.h" | #include "src/tint/transform/unwind_discard_functions.h" | ||||||
| #include "src/tint/transform/vectorize_scalar_matrix_constructors.h" | #include "src/tint/transform/vectorize_scalar_matrix_constructors.h" | ||||||
| #include "src/tint/transform/wrap_arrays_in_structs.h" |  | ||||||
| #include "src/tint/transform/zero_init_workgroup_memory.h" | #include "src/tint/transform/zero_init_workgroup_memory.h" | ||||||
| #include "src/tint/utils/defer.h" | #include "src/tint/utils/defer.h" | ||||||
| #include "src/tint/utils/map.h" | #include "src/tint/utils/map.h" | ||||||
| @ -208,7 +207,6 @@ SanitizedResult Sanitize(const Program* in, const Options& options) { | |||||||
|     manager.Add<transform::PromoteInitializersToConstVar>(); |     manager.Add<transform::PromoteInitializersToConstVar>(); | ||||||
| 
 | 
 | ||||||
|     manager.Add<transform::VectorizeScalarMatrixConstructors>(); |     manager.Add<transform::VectorizeScalarMatrixConstructors>(); | ||||||
|     manager.Add<transform::WrapArraysInStructs>(); |  | ||||||
|     manager.Add<transform::RemovePhonies>(); |     manager.Add<transform::RemovePhonies>(); | ||||||
|     manager.Add<transform::SimplifyPointers>(); |     manager.Add<transform::SimplifyPointers>(); | ||||||
|     // ArrayLengthFromUniform must come after SimplifyPointers, as
 |     // ArrayLengthFromUniform must come after SimplifyPointers, as
 | ||||||
| @ -731,13 +729,33 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out, | |||||||
|                                         const sem::TypeConstructor* ctor) { |                                         const sem::TypeConstructor* ctor) { | ||||||
|     auto* type = ctor->ReturnType(); |     auto* type = ctor->ReturnType(); | ||||||
| 
 | 
 | ||||||
|     if (type->IsAnyOf<sem::Array, sem::Struct>()) { |     const char* terminator = ")"; | ||||||
|         out << "{"; |     TINT_DEFER(out << terminator); | ||||||
|     } else { | 
 | ||||||
|         if (!EmitType(out, type, "")) { |     bool ok = Switch( | ||||||
|             return false; |         type, | ||||||
|         } |         [&](const sem::Array*) { | ||||||
|         out << "("; |             if (!EmitType(out, type, "")) { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             out << "{"; | ||||||
|  |             terminator = "}"; | ||||||
|  |             return true; | ||||||
|  |         }, | ||||||
|  |         [&](const sem::Struct*) { | ||||||
|  |             out << "{"; | ||||||
|  |             terminator = "}"; | ||||||
|  |             return true; | ||||||
|  |         }, | ||||||
|  |         [&](Default) { | ||||||
|  |             if (!EmitType(out, type, "")) { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             out << "("; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  |     if (!ok) { | ||||||
|  |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     int i = 0; |     int i = 0; | ||||||
| @ -760,11 +778,6 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& out, | |||||||
|         i++; |         i++; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (type->IsAnyOf<sem::Array, sem::Struct>()) { |  | ||||||
|         out << "}"; |  | ||||||
|     } else { |  | ||||||
|         out << ")"; |  | ||||||
|     } |  | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1561,10 +1574,9 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) { | |||||||
|             ScopedParen sp(out); |             ScopedParen sp(out); | ||||||
|             return EmitZeroValue(out, mat->type()); |             return EmitZeroValue(out, mat->type()); | ||||||
|         }, |         }, | ||||||
|         [&](const sem::Array* arr) { |         [&](const sem::Array*) { | ||||||
|             out << "{"; |             out << "{}"; | ||||||
|             TINT_DEFER(out << "}"); |             return true; | ||||||
|             return EmitZeroValue(out, arr->ElemType()); |  | ||||||
|         }, |         }, | ||||||
|         [&](const sem::Struct*) { |         [&](const sem::Struct*) { | ||||||
|             out << "{}"; |             out << "{}"; | ||||||
| @ -1772,8 +1784,8 @@ bool GeneratorImpl::EmitFunction(const ast::Function* func) { | |||||||
|             if (!EmitType(out, type, param_name)) { |             if (!EmitType(out, type, param_name)) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             // Parameter name is output as part of the type for arrays and pointers.
 |             // Parameter name is output as part of the type for pointers.
 | ||||||
|             if (!type->Is<sem::Array>() && !type->Is<sem::Pointer>()) { |             if (!type->Is<sem::Pointer>()) { | ||||||
|                 out << " " << program_->Symbols().NameFor(v->symbol); |                 out << " " << program_->Symbols().NameFor(v->symbol); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -1896,8 +1908,8 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) { | |||||||
|             if (!EmitType(out, type, param_name)) { |             if (!EmitType(out, type, param_name)) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             // Parameter name is output as part of the type for arrays and pointers.
 |             // Parameter name is output as part of the type for pointers.
 | ||||||
|             if (!type->Is<sem::Array>() && !type->Is<sem::Pointer>()) { |             if (!type->Is<sem::Pointer>()) { | ||||||
|                 out << " " << param_name; |                 out << " " << param_name; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -2412,29 +2424,12 @@ bool GeneratorImpl::EmitType(std::ostream& out, | |||||||
|                 << "unhandled atomic type " << atomic->Type()->FriendlyName(builder_.Symbols()); |                 << "unhandled atomic type " << atomic->Type()->FriendlyName(builder_.Symbols()); | ||||||
|             return false; |             return false; | ||||||
|         }, |         }, | ||||||
|         [&](const sem::Array* ary) { |         [&](const sem::Array* arr) { | ||||||
|             const sem::Type* base_type = ary; |             out << ArrayType() << "<"; | ||||||
|             std::vector<uint32_t> sizes; |             if (!EmitType(out, arr->ElemType(), "")) { | ||||||
|             while (auto* arr = base_type->As<sem::Array>()) { |  | ||||||
|                 if (arr->IsRuntimeSized()) { |  | ||||||
|                     sizes.push_back(1); |  | ||||||
|                 } else { |  | ||||||
|                     sizes.push_back(arr->Count()); |  | ||||||
|                 } |  | ||||||
|                 base_type = arr->ElemType(); |  | ||||||
|             } |  | ||||||
|             if (!EmitType(out, base_type, "")) { |  | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             if (!name.empty()) { |             out << ", " << (arr->IsRuntimeSized() ? 1u : arr->Count()) << ">"; | ||||||
|                 out << " " << name; |  | ||||||
|                 if (name_printed) { |  | ||||||
|                     *name_printed = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             for (uint32_t size : sizes) { |  | ||||||
|                 out << "[" << size << "]"; |  | ||||||
|             } |  | ||||||
|             return true; |             return true; | ||||||
|         }, |         }, | ||||||
|         [&](const sem::Bool*) { |         [&](const sem::Bool*) { | ||||||
| @ -2469,22 +2464,12 @@ bool GeneratorImpl::EmitType(std::ostream& out, | |||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             out << " "; |             out << " "; | ||||||
|             if (ptr->StoreType()->Is<sem::Array>()) { |             if (!EmitType(out, ptr->StoreType(), "")) { | ||||||
|                 std::string inner = "(*" + name + ")"; |                 return false; | ||||||
|                 if (!EmitType(out, ptr->StoreType(), inner)) { |             } | ||||||
|                     return false; |             out << "* " << name; | ||||||
|                 } |             if (name_printed) { | ||||||
|                 if (name_printed) { |                 *name_printed = true; | ||||||
|                     *name_printed = true; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 if (!EmitType(out, ptr->StoreType(), "")) { |  | ||||||
|                     return false; |  | ||||||
|                 } |  | ||||||
|                 out << "* " << name; |  | ||||||
|                 if (name_printed) { |  | ||||||
|                     *name_printed = true; |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         }, |         }, | ||||||
| @ -2700,7 +2685,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { | |||||||
| 
 | 
 | ||||||
|         auto out = line(b); |         auto out = line(b); | ||||||
|         add_byte_offset_comment(out, msl_offset); |         add_byte_offset_comment(out, msl_offset); | ||||||
|         out << "int8_t " << name << "[" << size << "];"; |         out << ArrayType() << "<int8_t, " << size << "> " << name << ";"; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     b->IncrementIndent(); |     b->IncrementIndent(); | ||||||
| @ -2738,11 +2723,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { | |||||||
| 
 | 
 | ||||||
|         auto* ty = mem->Type(); |         auto* ty = mem->Type(); | ||||||
| 
 | 
 | ||||||
|         // Array member name will be output with the type
 |         out << " " << mem_name; | ||||||
|         if (!ty->Is<sem::Array>()) { |  | ||||||
|             out << " " << mem_name; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Emit attributes
 |         // Emit attributes
 | ||||||
|         if (auto* decl = mem->Declaration()) { |         if (auto* decl = mem->Declaration()) { | ||||||
|             for (auto* attr : decl->attributes) { |             for (auto* attr : decl->attributes) { | ||||||
| @ -2945,8 +2926,8 @@ bool GeneratorImpl::EmitVar(const ast::Var* var) { | |||||||
|     if (!EmitType(out, type, name)) { |     if (!EmitType(out, type, name)) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     // Variable name is output as part of the type for arrays and pointers.
 |     // Variable name is output as part of the type for pointers.
 | ||||||
|     if (!type->Is<sem::Array>() && !type->Is<sem::Pointer>()) { |     if (!type->Is<sem::Pointer>()) { | ||||||
|         out << " " << name; |         out << " " << name; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -2995,8 +2976,8 @@ bool GeneratorImpl::EmitLet(const ast::Let* let) { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Variable name is output as part of the type for arrays and pointers.
 |     // Variable name is output as part of the type for pointers.
 | ||||||
|     if (!type->Is<sem::Array>() && !type->Is<sem::Pointer>()) { |     if (!type->Is<sem::Pointer>()) { | ||||||
|         out << " " << name; |         out << " " << name; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -3018,9 +2999,7 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Let* let) { | |||||||
|     if (!EmitType(out, type, program_->Symbols().NameFor(let->symbol))) { |     if (!EmitType(out, type, program_->Symbols().NameFor(let->symbol))) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     if (!type->Is<sem::Array>()) { |     out << " " << program_->Symbols().NameFor(let->symbol); | ||||||
|         out << " " << program_->Symbols().NameFor(let->symbol); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (let->constructor != nullptr) { |     if (let->constructor != nullptr) { | ||||||
|         out << " = "; |         out << " = "; | ||||||
| @ -3042,9 +3021,7 @@ bool GeneratorImpl::EmitOverride(const ast::Override* override) { | |||||||
|     if (!EmitType(out, type, program_->Symbols().NameFor(override->symbol))) { |     if (!EmitType(out, type, program_->Symbols().NameFor(override->symbol))) { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     if (!type->Is<sem::Array>()) { |     out << " " << program_->Symbols().NameFor(override->symbol); | ||||||
|         out << " " << program_->Symbols().NameFor(override->symbol); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     out << " [[function_constant(" << global->ConstantId() << ")]];"; |     out << " [[function_constant(" << global->ConstantId() << ")]];"; | ||||||
| 
 | 
 | ||||||
| @ -3117,8 +3094,8 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(const sem:: | |||||||
| 
 | 
 | ||||||
|         [&](const sem::Array* arr) { |         [&](const sem::Array* arr) { | ||||||
|             if (!arr->IsStrideImplicit()) { |             if (!arr->IsStrideImplicit()) { | ||||||
|                 TINT_ICE(Writer, diagnostics_) << "arrays with explicit strides not " |                 TINT_ICE(Writer, diagnostics_) | ||||||
|                                                   "exist past the SPIR-V reader"; |                     << "arrays with explicit strides should not exist past the SPIR-V reader"; | ||||||
|                 return SizeAndAlign{}; |                 return SizeAndAlign{}; | ||||||
|             } |             } | ||||||
|             auto num_els = std::max<uint32_t>(arr->Count(), 1); |             auto num_els = std::max<uint32_t>(arr->Count(), 1); | ||||||
| @ -3205,4 +3182,25 @@ bool GeneratorImpl::CallBuiltinHelper(std::ostream& out, | |||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const std::string& GeneratorImpl::ArrayType() { | ||||||
|  |     if (array_template_name_.empty()) { | ||||||
|  |         array_template_name_ = UniqueIdentifier("tint_array"); | ||||||
|  |         auto* buf = &helpers_; | ||||||
|  |         line(buf) << "template<typename T, size_t N>"; | ||||||
|  |         line(buf) << "struct " << array_template_name_ << " {"; | ||||||
|  |         line(buf) << "    const constant T& operator[](size_t i) const constant" | ||||||
|  |                   << " { return elements[i]; }"; | ||||||
|  |         for (auto* space : {"device", "thread", "threadgroup"}) { | ||||||
|  |             line(buf) << "    " << space << " T& operator[](size_t i) " << space | ||||||
|  |                       << " { return elements[i]; }"; | ||||||
|  |             line(buf) << "    const " << space << " T& operator[](size_t i) const " << space | ||||||
|  |                       << " { return elements[i]; }"; | ||||||
|  |         } | ||||||
|  |         line(buf) << "    T elements[N];"; | ||||||
|  |         line(buf) << "};"; | ||||||
|  |         line(buf); | ||||||
|  |     } | ||||||
|  |     return array_template_name_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| }  // namespace tint::writer::msl
 | }  // namespace tint::writer::msl
 | ||||||
|  | |||||||
| @ -425,6 +425,10 @@ class GeneratorImpl : public TextGenerator { | |||||||
|                            const sem::Builtin* builtin, |                            const sem::Builtin* builtin, | ||||||
|                            F&& build); |                            F&& build); | ||||||
| 
 | 
 | ||||||
|  |     /// @returns the name of the templated tint_array helper type, generating it if this is the
 | ||||||
|  |     /// first call.
 | ||||||
|  |     const std::string& ArrayType(); | ||||||
|  | 
 | ||||||
|     TextBuffer helpers_;  // Helper functions emitted at the top of the output
 |     TextBuffer helpers_;  // Helper functions emitted at the top of the output
 | ||||||
| 
 | 
 | ||||||
|     /// @returns the MSL packed type size and alignment in bytes for the given
 |     /// @returns the MSL packed type size and alignment in bytes for the given
 | ||||||
| @ -439,13 +443,17 @@ class GeneratorImpl : public TextGenerator { | |||||||
|         utils::UnorderedKeyWrapper<std::tuple<ast::StorageClass, const sem::Struct*>>; |         utils::UnorderedKeyWrapper<std::tuple<ast::StorageClass, const sem::Struct*>>; | ||||||
|     std::unordered_map<ACEWKeyType, std::string> atomicCompareExchangeWeak_; |     std::unordered_map<ACEWKeyType, std::string> atomicCompareExchangeWeak_; | ||||||
| 
 | 
 | ||||||
|     /// Unique name of the 'TINT_INVARIANT' preprocessor define. Non-empty only if
 |     /// Unique name of the 'TINT_INVARIANT' preprocessor define.
 | ||||||
|     /// an invariant attribute has been generated.
 |     /// Non-empty only if an invariant attribute has been generated.
 | ||||||
|     std::string invariant_define_name_; |     std::string invariant_define_name_; | ||||||
| 
 | 
 | ||||||
|     /// True if matrix-packed_vector operator overloads have been generated.
 |     /// True if matrix-packed_vector operator overloads have been generated.
 | ||||||
|     bool matrix_packed_vector_overloads_ = false; |     bool matrix_packed_vector_overloads_ = false; | ||||||
| 
 | 
 | ||||||
|  |     /// Unique name of the tint_array<T, N> template.
 | ||||||
|  |     /// Non-empty only if the template has been generated.
 | ||||||
|  |     std::string array_template_name_; | ||||||
|  | 
 | ||||||
|     /// A map from entry point name to a list of dynamic workgroup allocations.
 |     /// A map from entry point name to a list of dynamic workgroup allocations.
 | ||||||
|     /// Each entry in the vector is the size of the workgroup allocation that
 |     /// Each entry in the vector is the size of the workgroup allocation that
 | ||||||
|     /// should be created for that index.
 |     /// should be created for that index.
 | ||||||
|  | |||||||
| @ -591,11 +591,20 @@ TEST_F(MslGeneratorImplTest, Emit_Function_WithArrayParams) { | |||||||
|     EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib> |     EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
|   using namespace metal; |   using namespace metal; | ||||||
|   struct tint_array_wrapper { |  | ||||||
|     float arr[5]; |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   void my_func(tint_array_wrapper a) { | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  |   void my_func(tint_array<float, 5> a) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -616,12 +625,21 @@ TEST_F(MslGeneratorImplTest, Emit_Function_WithArrayReturn) { | |||||||
|     EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib> |     EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
|   using namespace metal; |   using namespace metal; | ||||||
|   struct tint_array_wrapper { |  | ||||||
|     float arr[5]; |  | ||||||
|   }; |  | ||||||
| 
 | 
 | ||||||
|   tint_array_wrapper my_func() { | template<typename T, size_t N> | ||||||
|     tint_array_wrapper const tint_symbol = {.arr={}}; | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  |   tint_array<float, 5> my_func() { | ||||||
|  |     tint_array<float, 5> const tint_symbol = tint_array<float, 5>{}; | ||||||
|     return tint_symbol; |     return tint_symbol; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) { | |||||||
|     GeneratorImpl& gen = Build(); |     GeneratorImpl& gen = Build(); | ||||||
| 
 | 
 | ||||||
|     ASSERT_TRUE(gen.EmitProgramConstVariable(var)) << gen.error(); |     ASSERT_TRUE(gen.EmitProgramConstVariable(var)) << gen.error(); | ||||||
|     EXPECT_EQ(gen.result(), "constant float pos[3] = {1.0f, 2.0f, 3.0f};\n"); |     EXPECT_EQ(gen.result(), "constant tint_array<float, 3> pos = tint_array<float, 3>{1.0f, 2.0f, 3.0f};\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, Emit_SpecConstant) { | TEST_F(MslGeneratorImplTest, Emit_SpecConstant) { | ||||||
|  | |||||||
| @ -50,12 +50,25 @@ TEST_F(MslSanitizerTest, Call_ArrayLength) { | |||||||
|     auto* expect = R"(#include <metal_stdlib> |     auto* expect = R"(#include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol { | struct tint_symbol { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct my_struct { | struct my_struct { | ||||||
|   float a[1]; |   tint_array<float, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(30)]]) { | fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(30)]]) { | ||||||
| @ -95,13 +108,26 @@ TEST_F(MslSanitizerTest, Call_ArrayLength_OtherMembersInStruct) { | |||||||
|     auto* expect = R"(#include <metal_stdlib> |     auto* expect = R"(#include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol { | struct tint_symbol { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct my_struct { | struct my_struct { | ||||||
|   float z; |   float z; | ||||||
|   float a[1]; |   tint_array<float, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(30)]]) { | fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(30)]]) { | ||||||
| @ -143,12 +169,25 @@ TEST_F(MslSanitizerTest, Call_ArrayLength_ViaLets) { | |||||||
|     auto* expect = R"(#include <metal_stdlib> |     auto* expect = R"(#include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol { | struct tint_symbol { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct my_struct { | struct my_struct { | ||||||
|   float a[1]; |   tint_array<float, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(30)]]) { | fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(30)]]) { | ||||||
| @ -196,12 +235,25 @@ TEST_F(MslSanitizerTest, Call_ArrayLength_ArrayLengthFromUniform) { | |||||||
|     auto* expect = R"(#include <metal_stdlib> |     auto* expect = R"(#include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol { | struct tint_symbol { | ||||||
|   /* 0x0000 */ uint4 buffer_size[2]; |   /* 0x0000 */ tint_array<uint4, 2> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct my_struct { | struct my_struct { | ||||||
|   float a[1]; |   tint_array<float, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(29)]]) { | fragment void a_func(const constant tint_symbol* tint_symbol_2 [[buffer(29)]]) { | ||||||
|  | |||||||
| @ -188,25 +188,34 @@ TEST_F(MslGeneratorImplTest, WorkgroupMatrixInArray) { | |||||||
|     EXPECT_EQ(gen.result(), R"(#include <metal_stdlib> |     EXPECT_EQ(gen.result(), R"(#include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   float2x2 arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_symbol_3 { | struct tint_symbol_3 { | ||||||
|   tint_array_wrapper m; |   tint_array<float2x2, 4> m; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void comp_main_inner(uint local_invocation_index, threadgroup tint_array_wrapper* const tint_symbol) { | void comp_main_inner(uint local_invocation_index, threadgroup tint_array<float2x2, 4>* const tint_symbol) { | ||||||
|   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) { |   for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) { | ||||||
|     uint const i = idx; |     uint const i = idx; | ||||||
|     (*(tint_symbol)).arr[i] = float2x2(float2(0.0f), float2(0.0f)); |     (*(tint_symbol))[i] = float2x2(float2(0.0f), float2(0.0f)); | ||||||
|   } |   } | ||||||
|   threadgroup_barrier(mem_flags::mem_threadgroup); |   threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
|   tint_array_wrapper const x = *(tint_symbol); |   tint_array<float2x2, 4> const x = *(tint_symbol); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void comp_main(threadgroup tint_symbol_3* tint_symbol_2 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | kernel void comp_main(threadgroup tint_symbol_3* tint_symbol_2 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | ||||||
|   threadgroup tint_array_wrapper* const tint_symbol_1 = &((*(tint_symbol_2)).m); |   threadgroup tint_array<float2x2, 4>* const tint_symbol_1 = &((*(tint_symbol_2)).m); | ||||||
|   comp_main_inner(local_invocation_index, tint_symbol_1); |   comp_main_inner(local_invocation_index, tint_symbol_1); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
|  | |||||||
| @ -31,6 +31,20 @@ using namespace tint::number_suffixes;  // NOLINT | |||||||
| namespace tint::writer::msl { | namespace tint::writer::msl { | ||||||
| namespace { | namespace { | ||||||
| 
 | 
 | ||||||
|  | void FormatMSLField(std::stringstream& out, | ||||||
|  |                     const char* addr, | ||||||
|  |                     const char* type, | ||||||
|  |                     size_t array_count, | ||||||
|  |                     const char* name) { | ||||||
|  |     out << "  /* " << std::string(addr) << " */ "; | ||||||
|  |     if (array_count == 0) { | ||||||
|  |         out << type << " "; | ||||||
|  |     } else { | ||||||
|  |         out << "tint_array<" << type << ", " << std::to_string(array_count) << "> "; | ||||||
|  |     } | ||||||
|  |     out << name << ";\n"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #define CHECK_TYPE_SIZE_AND_ALIGN(TYPE, SIZE, ALIGN)      \ | #define CHECK_TYPE_SIZE_AND_ALIGN(TYPE, SIZE, ALIGN)      \ | ||||||
|     static_assert(sizeof(TYPE) == SIZE, "Bad type size"); \ |     static_assert(sizeof(TYPE) == SIZE, "Bad type size"); \ | ||||||
|     static_assert(alignof(TYPE) == ALIGN, "Bad type alignment") |     static_assert(alignof(TYPE) == ALIGN, "Bad type alignment") | ||||||
| @ -69,7 +83,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Array) { | |||||||
| 
 | 
 | ||||||
|     std::stringstream out; |     std::stringstream out; | ||||||
|     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), "ary")) << gen.error(); |     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), "ary")) << gen.error(); | ||||||
|     EXPECT_EQ(out.str(), "bool ary[4]"); |     EXPECT_EQ(out.str(), "tint_array<bool, 4>"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArray) { | TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArray) { | ||||||
| @ -81,7 +95,7 @@ TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArray) { | |||||||
| 
 | 
 | ||||||
|     std::stringstream out; |     std::stringstream out; | ||||||
|     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(b), "ary")) << gen.error(); |     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(b), "ary")) << gen.error(); | ||||||
|     EXPECT_EQ(out.str(), "bool ary[5][4]"); |     EXPECT_EQ(out.str(), "tint_array<tint_array<bool, 4>, 5>"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArrayOfArray) { | TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArrayOfArray) { | ||||||
| @ -94,7 +108,7 @@ TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArrayOfArray) { | |||||||
| 
 | 
 | ||||||
|     std::stringstream out; |     std::stringstream out; | ||||||
|     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(c), "ary")) << gen.error(); |     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(c), "ary")) << gen.error(); | ||||||
|     EXPECT_EQ(out.str(), "bool ary[6][5][4]"); |     EXPECT_EQ(out.str(), "tint_array<tint_array<tint_array<bool, 4>, 5>, 6>"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, EmitType_Array_WithoutName) { | TEST_F(MslGeneratorImplTest, EmitType_Array_WithoutName) { | ||||||
| @ -105,7 +119,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Array_WithoutName) { | |||||||
| 
 | 
 | ||||||
|     std::stringstream out; |     std::stringstream out; | ||||||
|     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), "")) << gen.error(); |     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), "")) << gen.error(); | ||||||
|     EXPECT_EQ(out.str(), "bool[4]"); |     EXPECT_EQ(out.str(), "tint_array<bool, 4>"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, EmitType_RuntimeArray) { | TEST_F(MslGeneratorImplTest, EmitType_RuntimeArray) { | ||||||
| @ -116,7 +130,7 @@ TEST_F(MslGeneratorImplTest, EmitType_RuntimeArray) { | |||||||
| 
 | 
 | ||||||
|     std::stringstream out; |     std::stringstream out; | ||||||
|     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), "ary")) << gen.error(); |     ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), "ary")) << gen.error(); | ||||||
|     EXPECT_EQ(out.str(), "bool ary[1]"); |     EXPECT_EQ(out.str(), "tint_array<bool, 1>"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, EmitType_Bool) { | TEST_F(MslGeneratorImplTest, EmitType_Bool) { | ||||||
| @ -245,54 +259,58 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_NonComposites) { | |||||||
|     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); |     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); | ||||||
|     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); |     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); | ||||||
| 
 | 
 | ||||||
|     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, NAME, SUFFIX)
 |     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
 | ||||||
|     // for each field of the structure s.
 |     // for each field of the structure s.
 | ||||||
| #define ALL_FIELDS()                               \ | #define ALL_FIELDS()                       \ | ||||||
|     FIELD(0x0000, int, a, /*NO SUFFIX*/)           \ |     FIELD(0x0000, int, 0, a)               \ | ||||||
|     FIELD(0x0004, int8_t, tint_pad, [124])         \ |     FIELD(0x0004, int8_t, 124, tint_pad)   \ | ||||||
|     FIELD(0x0080, float, b, /*NO SUFFIX*/)         \ |     FIELD(0x0080, float, 0, b)             \ | ||||||
|     FIELD(0x0084, int8_t, tint_pad_1, [124])       \ |     FIELD(0x0084, int8_t, 124, tint_pad_1) \ | ||||||
|     FIELD(0x0100, float2, c, /*NO SUFFIX*/)        \ |     FIELD(0x0100, float2, 0, c)            \ | ||||||
|     FIELD(0x0108, uint, d, /*NO SUFFIX*/)          \ |     FIELD(0x0108, uint, 0, d)              \ | ||||||
|     FIELD(0x010c, int8_t, tint_pad_2, [4])         \ |     FIELD(0x010c, int8_t, 4, tint_pad_2)   \ | ||||||
|     FIELD(0x0110, packed_float3, e, /*NO SUFFIX*/) \ |     FIELD(0x0110, packed_float3, 0, e)     \ | ||||||
|     FIELD(0x011c, uint, f, /*NO SUFFIX*/)          \ |     FIELD(0x011c, uint, 0, f)              \ | ||||||
|     FIELD(0x0120, float4, g, /*NO SUFFIX*/)        \ |     FIELD(0x0120, float4, 0, g)            \ | ||||||
|     FIELD(0x0130, uint, h, /*NO SUFFIX*/)          \ |     FIELD(0x0130, uint, 0, h)              \ | ||||||
|     FIELD(0x0134, int8_t, tint_pad_3, [4])         \ |     FIELD(0x0134, int8_t, 4, tint_pad_3)   \ | ||||||
|     FIELD(0x0138, float2x2, i, /*NO SUFFIX*/)      \ |     FIELD(0x0138, float2x2, 0, i)          \ | ||||||
|     FIELD(0x0148, uint, j, /*NO SUFFIX*/)          \ |     FIELD(0x0148, uint, 0, j)              \ | ||||||
|     FIELD(0x014c, int8_t, tint_pad_4, [4])         \ |     FIELD(0x014c, int8_t, 4, tint_pad_4)   \ | ||||||
|     FIELD(0x0150, float2x3, k, /*NO SUFFIX*/)      \ |     FIELD(0x0150, float2x3, 0, k)          \ | ||||||
|     FIELD(0x0170, uint, l, /*NO SUFFIX*/)          \ |     FIELD(0x0170, uint, 0, l)              \ | ||||||
|     FIELD(0x0174, int8_t, tint_pad_5, [12])        \ |     FIELD(0x0174, int8_t, 12, tint_pad_5)  \ | ||||||
|     FIELD(0x0180, float2x4, m, /*NO SUFFIX*/)      \ |     FIELD(0x0180, float2x4, 0, m)          \ | ||||||
|     FIELD(0x01a0, uint, n, /*NO SUFFIX*/)          \ |     FIELD(0x01a0, uint, 0, n)              \ | ||||||
|     FIELD(0x01a4, int8_t, tint_pad_6, [4])         \ |     FIELD(0x01a4, int8_t, 4, tint_pad_6)   \ | ||||||
|     FIELD(0x01a8, float3x2, o, /*NO SUFFIX*/)      \ |     FIELD(0x01a8, float3x2, 0, o)          \ | ||||||
|     FIELD(0x01c0, uint, p, /*NO SUFFIX*/)          \ |     FIELD(0x01c0, uint, 0, p)              \ | ||||||
|     FIELD(0x01c4, int8_t, tint_pad_7, [12])        \ |     FIELD(0x01c4, int8_t, 12, tint_pad_7)  \ | ||||||
|     FIELD(0x01d0, float3x3, q, /*NO SUFFIX*/)      \ |     FIELD(0x01d0, float3x3, 0, q)          \ | ||||||
|     FIELD(0x0200, uint, r, /*NO SUFFIX*/)          \ |     FIELD(0x0200, uint, 0, r)              \ | ||||||
|     FIELD(0x0204, int8_t, tint_pad_8, [12])        \ |     FIELD(0x0204, int8_t, 12, tint_pad_8)  \ | ||||||
|     FIELD(0x0210, float3x4, s, /*NO SUFFIX*/)      \ |     FIELD(0x0210, float3x4, 0, s)          \ | ||||||
|     FIELD(0x0240, uint, t, /*NO SUFFIX*/)          \ |     FIELD(0x0240, uint, 0, t)              \ | ||||||
|     FIELD(0x0244, int8_t, tint_pad_9, [4])         \ |     FIELD(0x0244, int8_t, 4, tint_pad_9)   \ | ||||||
|     FIELD(0x0248, float4x2, u, /*NO SUFFIX*/)      \ |     FIELD(0x0248, float4x2, 0, u)          \ | ||||||
|     FIELD(0x0268, uint, v, /*NO SUFFIX*/)          \ |     FIELD(0x0268, uint, 0, v)              \ | ||||||
|     FIELD(0x026c, int8_t, tint_pad_10, [4])        \ |     FIELD(0x026c, int8_t, 4, tint_pad_10)  \ | ||||||
|     FIELD(0x0270, float4x3, w, /*NO SUFFIX*/)      \ |     FIELD(0x0270, float4x3, 0, w)          \ | ||||||
|     FIELD(0x02b0, uint, x, /*NO SUFFIX*/)          \ |     FIELD(0x02b0, uint, 0, x)              \ | ||||||
|     FIELD(0x02b4, int8_t, tint_pad_11, [12])       \ |     FIELD(0x02b4, int8_t, 12, tint_pad_11) \ | ||||||
|     FIELD(0x02c0, float4x4, y, /*NO SUFFIX*/)      \ |     FIELD(0x02c0, float4x4, 0, y)          \ | ||||||
|     FIELD(0x0300, float, z, /*NO SUFFIX*/)         \ |     FIELD(0x0300, float, 0, z)             \ | ||||||
|     FIELD(0x0304, int8_t, tint_pad_12, [124]) |     FIELD(0x0304, int8_t, 124, tint_pad_12) | ||||||
| 
 | 
 | ||||||
|     // Check that the generated string is as expected.
 |     // Check that the generated string is as expected.
 | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) "  /* " #ADDR " */ " #TYPE " " #NAME #SUFFIX ";\n" |     std::stringstream expect; | ||||||
|     auto* expect = "struct S {\n" ALL_FIELDS() "};\n"; |     expect << "struct S {\n"; | ||||||
|  | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ | ||||||
|  |     FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); | ||||||
|  |     ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
|     EXPECT_EQ(buf.String(), expect); |     expect << "};\n"; | ||||||
|  |     EXPECT_EQ(buf.String(), expect.str()); | ||||||
| 
 | 
 | ||||||
|     // 1.4 Metal and C++14
 |     // 1.4 Metal and C++14
 | ||||||
|     // The Metal programming language is a C++14-based Specification with
 |     // The Metal programming language is a C++14-based Specification with
 | ||||||
| @ -304,12 +322,12 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_NonComposites) { | |||||||
|     // layout is as expected for C++14 / MSL.
 |     // layout is as expected for C++14 / MSL.
 | ||||||
|     { |     { | ||||||
|         struct S { |         struct S { | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) TYPE NAME SUFFIX; | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME; | ||||||
|             ALL_FIELDS() |             ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) \ | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ | ||||||
|     EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME; |     EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME; | ||||||
|         ALL_FIELDS() |         ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
| @ -350,22 +368,26 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_Structures) { | |||||||
|     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); |     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); | ||||||
|     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); |     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); | ||||||
| 
 | 
 | ||||||
|     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, NAME, SUFFIX)
 |     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
 | ||||||
|     // for each field of the structure s.
 |     // for each field of the structure s.
 | ||||||
| #define ALL_FIELDS()                         \ | #define ALL_FIELDS()                     \ | ||||||
|     FIELD(0x0000, int, a, /*NO SUFFIX*/)     \ |     FIELD(0x0000, int, 0, a)             \ | ||||||
|     FIELD(0x0004, int8_t, tint_pad, [508])   \ |     FIELD(0x0004, int8_t, 508, tint_pad) \ | ||||||
|     FIELD(0x0200, inner_x, b, /*NO SUFFIX*/) \ |     FIELD(0x0200, inner_x, 0, b)         \ | ||||||
|     FIELD(0x0600, float, c, /*NO SUFFIX*/)   \ |     FIELD(0x0600, float, 0, c)           \ | ||||||
|     FIELD(0x0604, inner_y, d, /*NO SUFFIX*/) \ |     FIELD(0x0604, inner_y, 0, d)         \ | ||||||
|     FIELD(0x0808, float, e, /*NO SUFFIX*/)   \ |     FIELD(0x0808, float, 0, e)           \ | ||||||
|     FIELD(0x080c, int8_t, tint_pad_1, [500]) |     FIELD(0x080c, int8_t, 500, tint_pad_1) | ||||||
| 
 | 
 | ||||||
|     // Check that the generated string is as expected.
 |     // Check that the generated string is as expected.
 | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) "  /* " #ADDR " */ " #TYPE " " #NAME #SUFFIX ";\n" |     std::stringstream expect; | ||||||
|     auto* expect = "struct S {\n" ALL_FIELDS() "};\n"; |     expect << "struct S {\n"; | ||||||
|  | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ | ||||||
|  |     FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); | ||||||
|  |     ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
|     EXPECT_EQ(buf.String(), expect); |     expect << "};\n"; | ||||||
|  |     EXPECT_EQ(buf.String(), expect.str()); | ||||||
| 
 | 
 | ||||||
|     // 1.4 Metal and C++14
 |     // 1.4 Metal and C++14
 | ||||||
|     // The Metal programming language is a C++14-based Specification with
 |     // The Metal programming language is a C++14-based Specification with
 | ||||||
| @ -389,12 +411,12 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_Structures) { | |||||||
|         CHECK_TYPE_SIZE_AND_ALIGN(inner_y, 516, 4); |         CHECK_TYPE_SIZE_AND_ALIGN(inner_y, 516, 4); | ||||||
| 
 | 
 | ||||||
|         struct S { |         struct S { | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) TYPE NAME SUFFIX; | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME; | ||||||
|             ALL_FIELDS() |             ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) \ | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ | ||||||
|     EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME; |     EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME; | ||||||
|         ALL_FIELDS() |         ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
| @ -440,23 +462,27 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayDefaultStride) { | |||||||
|     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); |     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); | ||||||
|     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); |     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); | ||||||
| 
 | 
 | ||||||
|     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, NAME, SUFFIX)
 |     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
 | ||||||
|     // for each field of the structure s.
 |     // for each field of the structure s.
 | ||||||
| #define ALL_FIELDS()                       \ | #define ALL_FIELDS()                     \ | ||||||
|     FIELD(0x0000, int, a, /*NO SUFFIX*/)   \ |     FIELD(0x0000, int, 0, a)             \ | ||||||
|     FIELD(0x0004, float, b, [7])           \ |     FIELD(0x0004, float, 7, b)           \ | ||||||
|     FIELD(0x0020, float, c, /*NO SUFFIX*/) \ |     FIELD(0x0020, float, 0, c)           \ | ||||||
|     FIELD(0x0024, int8_t, tint_pad, [476]) \ |     FIELD(0x0024, int8_t, 476, tint_pad) \ | ||||||
|     FIELD(0x0200, inner, d, [4])           \ |     FIELD(0x0200, inner, 4, d)           \ | ||||||
|     FIELD(0x1200, float, e, /*NO SUFFIX*/) \ |     FIELD(0x1200, float, 0, e)           \ | ||||||
|     FIELD(0x1204, float, f, [1])           \ |     FIELD(0x1204, float, 1, f)           \ | ||||||
|     FIELD(0x1208, int8_t, tint_pad_1, [504]) |     FIELD(0x1208, int8_t, 504, tint_pad_1) | ||||||
| 
 | 
 | ||||||
|     // Check that the generated string is as expected.
 |     // Check that the generated string is as expected.
 | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) "  /* " #ADDR " */ " #TYPE " " #NAME #SUFFIX ";\n" |     std::stringstream expect; | ||||||
|     auto* expect = "struct S {\n" ALL_FIELDS() "};\n"; |     expect << "struct S {\n"; | ||||||
|  | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ | ||||||
|  |     FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); | ||||||
|  |     ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
|     EXPECT_EQ(buf.String(), expect); |     expect << "};\n"; | ||||||
|  |     EXPECT_EQ(buf.String(), expect.str()); | ||||||
| 
 | 
 | ||||||
|     // 1.4 Metal and C++14
 |     // 1.4 Metal and C++14
 | ||||||
|     // The Metal programming language is a C++14-based Specification with
 |     // The Metal programming language is a C++14-based Specification with
 | ||||||
| @ -486,12 +512,12 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayDefaultStride) { | |||||||
|         CHECK_TYPE_SIZE_AND_ALIGN(array_z, 4, 4); |         CHECK_TYPE_SIZE_AND_ALIGN(array_z, 4, 4); | ||||||
| 
 | 
 | ||||||
|         struct S { |         struct S { | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) TYPE NAME SUFFIX; | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME; | ||||||
|             ALL_FIELDS() |             ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) \ | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ | ||||||
|     EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME; |     EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME; | ||||||
|         ALL_FIELDS() |         ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
| @ -522,20 +548,24 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayVec3DefaultStride) { | |||||||
|     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); |     auto* sem_s = program->TypeOf(s)->As<sem::Struct>(); | ||||||
|     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); |     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); | ||||||
| 
 | 
 | ||||||
|     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, NAME, SUFFIX)
 |     // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
 | ||||||
|     // for each field of the structure s.
 |     // for each field of the structure s.
 | ||||||
| #define ALL_FIELDS()                      \ | #define ALL_FIELDS()                    \ | ||||||
|     FIELD(0x0000, int, a, /*NO SUFFIX*/)  \ |     FIELD(0x0000, int, 0, a)            \ | ||||||
|     FIELD(0x0004, int8_t, tint_pad, [12]) \ |     FIELD(0x0004, int8_t, 12, tint_pad) \ | ||||||
|     FIELD(0x0010, float3, b, [4])         \ |     FIELD(0x0010, float3, 4, b)         \ | ||||||
|     FIELD(0x0050, int, c, /*NO SUFFIX*/)  \ |     FIELD(0x0050, int, 0, c)            \ | ||||||
|     FIELD(0x0054, int8_t, tint_pad_1, [12]) |     FIELD(0x0054, int8_t, 12, tint_pad_1) | ||||||
| 
 | 
 | ||||||
|     // Check that the generated string is as expected.
 |     // Check that the generated string is as expected.
 | ||||||
| #define FIELD(ADDR, TYPE, NAME, SUFFIX) "  /* " #ADDR " */ " #TYPE " " #NAME #SUFFIX ";\n" |     std::stringstream expect; | ||||||
|     auto* expect = "struct S {\n" ALL_FIELDS() "};\n"; |     expect << "struct S {\n"; | ||||||
|  | #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ | ||||||
|  |     FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); | ||||||
|  |     ALL_FIELDS() | ||||||
| #undef FIELD | #undef FIELD | ||||||
|     EXPECT_EQ(buf.String(), expect); |     expect << "};\n"; | ||||||
|  |     EXPECT_EQ(buf.String(), expect.str()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, AttemptTintPadSymbolCollision) { | TEST_F(MslGeneratorImplTest, AttemptTintPadSymbolCollision) { | ||||||
| @ -583,44 +613,44 @@ TEST_F(MslGeneratorImplTest, AttemptTintPadSymbolCollision) { | |||||||
|     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); |     ASSERT_TRUE(gen.EmitStructType(&buf, sem_s)) << gen.error(); | ||||||
|     EXPECT_EQ(buf.String(), R"(struct S { |     EXPECT_EQ(buf.String(), R"(struct S { | ||||||
|   /* 0x0000 */ int tint_pad_2; |   /* 0x0000 */ int tint_pad_2; | ||||||
|   /* 0x0004 */ int8_t tint_pad_10[124]; |   /* 0x0004 */ tint_array<int8_t, 124> tint_pad_10; | ||||||
|   /* 0x0080 */ float tint_pad_20; |   /* 0x0080 */ float tint_pad_20; | ||||||
|   /* 0x0084 */ int8_t tint_pad_11[124]; |   /* 0x0084 */ tint_array<int8_t, 124> tint_pad_11; | ||||||
|   /* 0x0100 */ float2 tint_pad_33; |   /* 0x0100 */ float2 tint_pad_33; | ||||||
|   /* 0x0108 */ uint tint_pad_1; |   /* 0x0108 */ uint tint_pad_1; | ||||||
|   /* 0x010c */ int8_t tint_pad_12[4]; |   /* 0x010c */ tint_array<int8_t, 4> tint_pad_12; | ||||||
|   /* 0x0110 */ packed_float3 tint_pad_3; |   /* 0x0110 */ packed_float3 tint_pad_3; | ||||||
|   /* 0x011c */ uint tint_pad_7; |   /* 0x011c */ uint tint_pad_7; | ||||||
|   /* 0x0120 */ float4 tint_pad_25; |   /* 0x0120 */ float4 tint_pad_25; | ||||||
|   /* 0x0130 */ uint tint_pad_5; |   /* 0x0130 */ uint tint_pad_5; | ||||||
|   /* 0x0134 */ int8_t tint_pad_13[4]; |   /* 0x0134 */ tint_array<int8_t, 4> tint_pad_13; | ||||||
|   /* 0x0138 */ float2x2 tint_pad_27; |   /* 0x0138 */ float2x2 tint_pad_27; | ||||||
|   /* 0x0148 */ uint tint_pad_24; |   /* 0x0148 */ uint tint_pad_24; | ||||||
|   /* 0x014c */ int8_t tint_pad_14[4]; |   /* 0x014c */ tint_array<int8_t, 4> tint_pad_14; | ||||||
|   /* 0x0150 */ float2x3 tint_pad_23; |   /* 0x0150 */ float2x3 tint_pad_23; | ||||||
|   /* 0x0170 */ uint tint_pad; |   /* 0x0170 */ uint tint_pad; | ||||||
|   /* 0x0174 */ int8_t tint_pad_15[12]; |   /* 0x0174 */ tint_array<int8_t, 12> tint_pad_15; | ||||||
|   /* 0x0180 */ float2x4 tint_pad_8; |   /* 0x0180 */ float2x4 tint_pad_8; | ||||||
|   /* 0x01a0 */ uint tint_pad_26; |   /* 0x01a0 */ uint tint_pad_26; | ||||||
|   /* 0x01a4 */ int8_t tint_pad_16[4]; |   /* 0x01a4 */ tint_array<int8_t, 4> tint_pad_16; | ||||||
|   /* 0x01a8 */ float3x2 tint_pad_29; |   /* 0x01a8 */ float3x2 tint_pad_29; | ||||||
|   /* 0x01c0 */ uint tint_pad_6; |   /* 0x01c0 */ uint tint_pad_6; | ||||||
|   /* 0x01c4 */ int8_t tint_pad_17[12]; |   /* 0x01c4 */ tint_array<int8_t, 12> tint_pad_17; | ||||||
|   /* 0x01d0 */ float3x3 tint_pad_22; |   /* 0x01d0 */ float3x3 tint_pad_22; | ||||||
|   /* 0x0200 */ uint tint_pad_32; |   /* 0x0200 */ uint tint_pad_32; | ||||||
|   /* 0x0204 */ int8_t tint_pad_18[12]; |   /* 0x0204 */ tint_array<int8_t, 12> tint_pad_18; | ||||||
|   /* 0x0210 */ float3x4 tint_pad_34; |   /* 0x0210 */ float3x4 tint_pad_34; | ||||||
|   /* 0x0240 */ uint tint_pad_35; |   /* 0x0240 */ uint tint_pad_35; | ||||||
|   /* 0x0244 */ int8_t tint_pad_19[4]; |   /* 0x0244 */ tint_array<int8_t, 4> tint_pad_19; | ||||||
|   /* 0x0248 */ float4x2 tint_pad_30; |   /* 0x0248 */ float4x2 tint_pad_30; | ||||||
|   /* 0x0268 */ uint tint_pad_9; |   /* 0x0268 */ uint tint_pad_9; | ||||||
|   /* 0x026c */ int8_t tint_pad_36[4]; |   /* 0x026c */ tint_array<int8_t, 4> tint_pad_36; | ||||||
|   /* 0x0270 */ float4x3 tint_pad_31; |   /* 0x0270 */ float4x3 tint_pad_31; | ||||||
|   /* 0x02b0 */ uint tint_pad_28; |   /* 0x02b0 */ uint tint_pad_28; | ||||||
|   /* 0x02b4 */ int8_t tint_pad_37[12]; |   /* 0x02b4 */ tint_array<int8_t, 12> tint_pad_37; | ||||||
|   /* 0x02c0 */ float4x4 tint_pad_4; |   /* 0x02c0 */ float4x4 tint_pad_4; | ||||||
|   /* 0x0300 */ float tint_pad_21; |   /* 0x0300 */ float tint_pad_21; | ||||||
|   /* 0x0304 */ int8_t tint_pad_38[124]; |   /* 0x0304 */ tint_array<int8_t, 124> tint_pad_38; | ||||||
| }; | }; | ||||||
| )"); | )"); | ||||||
| } | } | ||||||
|  | |||||||
| @ -61,7 +61,7 @@ TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Array) { | |||||||
|     gen.increment_indent(); |     gen.increment_indent(); | ||||||
| 
 | 
 | ||||||
|     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); |     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); | ||||||
|     EXPECT_EQ(gen.result(), "  float a[5] = {0.0f};\n"); |     EXPECT_EQ(gen.result(), "  tint_array<float, 5> a = {};\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Struct) { | TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Struct) { | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ int4 arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ tint_array_wrapper arr; |   /* 0x0000 */ tint_array<int4, 4> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| tint_array_wrapper ret_arr() { | tint_array<int4, 4> ret_arr() { | ||||||
|   tint_array_wrapper const tint_symbol_1 = {.arr={}}; |   tint_array<int4, 4> const tint_symbol_1 = tint_array<int4, 4>{}; | ||||||
|   return tint_symbol_1; |   return tint_symbol_1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -19,26 +28,14 @@ S ret_struct_arr() { | |||||||
|   return tint_symbol_2; |   return tint_symbol_2; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_3 { | void foo(tint_array<int4, 4> src_param, thread tint_array<int4, 4>* const tint_symbol_4, threadgroup tint_array<int4, 4>* const tint_symbol_5, const constant S* const tint_symbol_6, device S* const tint_symbol_7) { | ||||||
|   int arr[2]; |   tint_array<int4, 4> src_function = {}; | ||||||
| }; |   tint_array<int4, 4> dst = {}; | ||||||
| 
 |   tint_array<int4, 4> const tint_symbol_3 = tint_array<int4, 4>{int4(1), int4(2), int4(3), int4(3)}; | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   tint_array_wrapper_3 arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   tint_array_wrapper_2 arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void foo(tint_array_wrapper src_param, thread tint_array_wrapper* const tint_symbol_4, threadgroup tint_array_wrapper* const tint_symbol_5, const constant S* const tint_symbol_6, device S* const tint_symbol_7) { |  | ||||||
|   tint_array_wrapper src_function = {}; |  | ||||||
|   tint_array_wrapper dst = {}; |  | ||||||
|   tint_array_wrapper const tint_symbol_3 = {.arr={int4(1), int4(2), int4(3), int4(3)}}; |  | ||||||
|   dst = tint_symbol_3; |   dst = tint_symbol_3; | ||||||
|   dst = src_param; |   dst = src_param; | ||||||
|   dst = ret_arr(); |   dst = ret_arr(); | ||||||
|   tint_array_wrapper const src_let = {.arr={}}; |   tint_array<int4, 4> const src_let = tint_array<int4, 4>{}; | ||||||
|   dst = src_let; |   dst = src_let; | ||||||
|   dst = src_function; |   dst = src_function; | ||||||
|   dst = *(tint_symbol_4); |   dst = *(tint_symbol_4); | ||||||
| @ -47,8 +44,8 @@ void foo(tint_array_wrapper src_param, thread tint_array_wrapper* const tint_sym | |||||||
|   dst = tint_symbol.arr; |   dst = tint_symbol.arr; | ||||||
|   dst = (*(tint_symbol_6)).arr; |   dst = (*(tint_symbol_6)).arr; | ||||||
|   dst = (*(tint_symbol_7)).arr; |   dst = (*(tint_symbol_7)).arr; | ||||||
|   tint_array_wrapper_1 dst_nested = {}; |   tint_array<tint_array<tint_array<int, 2>, 3>, 4> dst_nested = {}; | ||||||
|   tint_array_wrapper_1 src_nested = {}; |   tint_array<tint_array<tint_array<int, 2>, 3>, 4> src_nested = {}; | ||||||
|   dst_nested = src_nested; |   dst_nested = src_nested; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,28 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ int4 arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ tint_array_wrapper arr; |   /* 0x0000 */ tint_array<int4, 4> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_3 { | tint_array<int4, 4> ret_arr() { | ||||||
|   int arr[2]; |   tint_array<int4, 4> const tint_symbol_1 = tint_array<int4, 4>{}; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   tint_array_wrapper_3 arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   tint_array_wrapper_2 arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| tint_array_wrapper ret_arr() { |  | ||||||
|   tint_array_wrapper const tint_symbol_1 = {.arr={}}; |  | ||||||
|   return tint_symbol_1; |   return tint_symbol_1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -31,13 +28,13 @@ S ret_struct_arr() { | |||||||
|   return tint_symbol_2; |   return tint_symbol_2; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void foo(tint_array_wrapper src_param, thread tint_array_wrapper* const tint_symbol_4, thread tint_array_wrapper* const tint_symbol_5, threadgroup tint_array_wrapper* const tint_symbol_6, const constant S* const tint_symbol_7, device S* const tint_symbol_8, thread tint_array_wrapper_1* const tint_symbol_9) { | void foo(tint_array<int4, 4> src_param, thread tint_array<int4, 4>* const tint_symbol_4, thread tint_array<int4, 4>* const tint_symbol_5, threadgroup tint_array<int4, 4>* const tint_symbol_6, const constant S* const tint_symbol_7, device S* const tint_symbol_8, thread tint_array<tint_array<tint_array<int, 2>, 3>, 4>* const tint_symbol_9) { | ||||||
|   tint_array_wrapper src_function = {}; |   tint_array<int4, 4> src_function = {}; | ||||||
|   tint_array_wrapper const tint_symbol_3 = {.arr={int4(1), int4(2), int4(3), int4(3)}}; |   tint_array<int4, 4> const tint_symbol_3 = tint_array<int4, 4>{int4(1), int4(2), int4(3), int4(3)}; | ||||||
|   *(tint_symbol_4) = tint_symbol_3; |   *(tint_symbol_4) = tint_symbol_3; | ||||||
|   *(tint_symbol_4) = src_param; |   *(tint_symbol_4) = src_param; | ||||||
|   *(tint_symbol_4) = ret_arr(); |   *(tint_symbol_4) = ret_arr(); | ||||||
|   tint_array_wrapper const src_let = {.arr={}}; |   tint_array<int4, 4> const src_let = tint_array<int4, 4>{}; | ||||||
|   *(tint_symbol_4) = src_let; |   *(tint_symbol_4) = src_let; | ||||||
|   *(tint_symbol_4) = src_function; |   *(tint_symbol_4) = src_function; | ||||||
|   *(tint_symbol_4) = *(tint_symbol_5); |   *(tint_symbol_4) = *(tint_symbol_5); | ||||||
| @ -46,7 +43,7 @@ void foo(tint_array_wrapper src_param, thread tint_array_wrapper* const tint_sym | |||||||
|   *(tint_symbol_4) = tint_symbol.arr; |   *(tint_symbol_4) = tint_symbol.arr; | ||||||
|   *(tint_symbol_4) = (*(tint_symbol_7)).arr; |   *(tint_symbol_4) = (*(tint_symbol_7)).arr; | ||||||
|   *(tint_symbol_4) = (*(tint_symbol_8)).arr; |   *(tint_symbol_4) = (*(tint_symbol_8)).arr; | ||||||
|   tint_array_wrapper_1 src_nested = {}; |   tint_array<tint_array<tint_array<int, 2>, 3>, 4> src_nested = {}; | ||||||
|   *(tint_symbol_9) = src_nested; |   *(tint_symbol_9) = src_nested; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,32 +1,29 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ int4 arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ tint_array_wrapper arr; |   /* 0x0000 */ tint_array<int4, 4> arr; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_3 { |  | ||||||
|   /* 0x0000 */ int arr[2]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   /* 0x0000 */ tint_array_wrapper_3 arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   /* 0x0000 */ tint_array_wrapper_2 arr[4]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S_nested { | struct S_nested { | ||||||
|   /* 0x0000 */ tint_array_wrapper_1 arr; |   /* 0x0000 */ tint_array<tint_array<tint_array<int, 2>, 3>, 4> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| tint_array_wrapper ret_arr() { | tint_array<int4, 4> ret_arr() { | ||||||
|   tint_array_wrapper const tint_symbol_2 = {.arr={}}; |   tint_array<int4, 4> const tint_symbol_2 = tint_array<int4, 4>{}; | ||||||
|   return tint_symbol_2; |   return tint_symbol_2; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -35,14 +32,14 @@ S ret_struct_arr() { | |||||||
|   return tint_symbol_3; |   return tint_symbol_3; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void foo(tint_array_wrapper src_param, device S* const tint_symbol_5, thread tint_array_wrapper* const tint_symbol_6, threadgroup tint_array_wrapper* const tint_symbol_7, const constant S* const tint_symbol_8, device S* const tint_symbol_9, device S_nested* const tint_symbol_10) { | void foo(tint_array<int4, 4> src_param, device S* const tint_symbol_5, thread tint_array<int4, 4>* const tint_symbol_6, threadgroup tint_array<int4, 4>* const tint_symbol_7, const constant S* const tint_symbol_8, device S* const tint_symbol_9, device S_nested* const tint_symbol_10) { | ||||||
|   tint_array_wrapper src_function = {}; |   tint_array<int4, 4> src_function = {}; | ||||||
|   tint_array_wrapper const tint_symbol_4 = {.arr={int4(1), int4(2), int4(3), int4(3)}}; |   tint_array<int4, 4> const tint_symbol_4 = tint_array<int4, 4>{int4(1), int4(2), int4(3), int4(3)}; | ||||||
|   (*(tint_symbol_5)).arr = tint_symbol_4; |   (*(tint_symbol_5)).arr = tint_symbol_4; | ||||||
|   (*(tint_symbol_5)).arr = src_param; |   (*(tint_symbol_5)).arr = src_param; | ||||||
|   tint_array_wrapper const tint_symbol = ret_arr(); |   tint_array<int4, 4> const tint_symbol = ret_arr(); | ||||||
|   (*(tint_symbol_5)).arr = tint_symbol; |   (*(tint_symbol_5)).arr = tint_symbol; | ||||||
|   tint_array_wrapper const src_let = {.arr={}}; |   tint_array<int4, 4> const src_let = tint_array<int4, 4>{}; | ||||||
|   (*(tint_symbol_5)).arr = src_let; |   (*(tint_symbol_5)).arr = src_let; | ||||||
|   (*(tint_symbol_5)).arr = src_function; |   (*(tint_symbol_5)).arr = src_function; | ||||||
|   (*(tint_symbol_5)).arr = *(tint_symbol_6); |   (*(tint_symbol_5)).arr = *(tint_symbol_6); | ||||||
| @ -51,7 +48,7 @@ void foo(tint_array_wrapper src_param, device S* const tint_symbol_5, thread tin | |||||||
|   (*(tint_symbol_5)).arr = tint_symbol_1.arr; |   (*(tint_symbol_5)).arr = tint_symbol_1.arr; | ||||||
|   (*(tint_symbol_5)).arr = (*(tint_symbol_8)).arr; |   (*(tint_symbol_5)).arr = (*(tint_symbol_8)).arr; | ||||||
|   (*(tint_symbol_5)).arr = (*(tint_symbol_9)).arr; |   (*(tint_symbol_5)).arr = (*(tint_symbol_9)).arr; | ||||||
|   tint_array_wrapper_1 src_nested = {}; |   tint_array<tint_array<tint_array<int, 2>, 3>, 4> src_nested = {}; | ||||||
|   (*(tint_symbol_10)).arr = src_nested; |   (*(tint_symbol_10)).arr = src_nested; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,27 +1,32 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   int arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper arr; |   tint_array<int, 4> arr; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   tint_array_wrapper arr[2]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void foo() { | void foo() { | ||||||
|   tint_array_wrapper const src = {.arr={}}; |   tint_array<int, 4> const src = tint_array<int, 4>{}; | ||||||
|   tint_array_wrapper dst = {}; |   tint_array<int, 4> dst = {}; | ||||||
|   S dst_struct = {}; |   S dst_struct = {}; | ||||||
|   tint_array_wrapper_1 dst_array = {}; |   tint_array<tint_array<int, 4>, 2> dst_array = {}; | ||||||
|   dst_struct.arr = src; |   dst_struct.arr = src; | ||||||
|   dst_array.arr[1] = src; |   dst_array[1] = src; | ||||||
|   dst = src; |   dst = src; | ||||||
|   dst_struct.arr = src; |   dst_struct.arr = src; | ||||||
|   dst_array.arr[0] = src; |   dst_array[0] = src; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,28 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ int4 arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ tint_array_wrapper arr; |   /* 0x0000 */ tint_array<int4, 4> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_3 { | tint_array<int4, 4> ret_arr() { | ||||||
|   int arr[2]; |   tint_array<int4, 4> const tint_symbol_1 = tint_array<int4, 4>{}; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   tint_array_wrapper_3 arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   tint_array_wrapper_2 arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| tint_array_wrapper ret_arr() { |  | ||||||
|   tint_array_wrapper const tint_symbol_1 = {.arr={}}; |  | ||||||
|   return tint_symbol_1; |   return tint_symbol_1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -31,13 +28,13 @@ S ret_struct_arr() { | |||||||
|   return tint_symbol_2; |   return tint_symbol_2; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void foo(tint_array_wrapper src_param, threadgroup tint_array_wrapper* const tint_symbol_4, thread tint_array_wrapper* const tint_symbol_5, threadgroup tint_array_wrapper* const tint_symbol_6, const constant S* const tint_symbol_7, device S* const tint_symbol_8, threadgroup tint_array_wrapper_1* const tint_symbol_9) { | void foo(tint_array<int4, 4> src_param, threadgroup tint_array<int4, 4>* const tint_symbol_4, thread tint_array<int4, 4>* const tint_symbol_5, threadgroup tint_array<int4, 4>* const tint_symbol_6, const constant S* const tint_symbol_7, device S* const tint_symbol_8, threadgroup tint_array<tint_array<tint_array<int, 2>, 3>, 4>* const tint_symbol_9) { | ||||||
|   tint_array_wrapper src_function = {}; |   tint_array<int4, 4> src_function = {}; | ||||||
|   tint_array_wrapper const tint_symbol_3 = {.arr={int4(1), int4(2), int4(3), int4(3)}}; |   tint_array<int4, 4> const tint_symbol_3 = tint_array<int4, 4>{int4(1), int4(2), int4(3), int4(3)}; | ||||||
|   *(tint_symbol_4) = tint_symbol_3; |   *(tint_symbol_4) = tint_symbol_3; | ||||||
|   *(tint_symbol_4) = src_param; |   *(tint_symbol_4) = src_param; | ||||||
|   *(tint_symbol_4) = ret_arr(); |   *(tint_symbol_4) = ret_arr(); | ||||||
|   tint_array_wrapper const src_let = {.arr={}}; |   tint_array<int4, 4> const src_let = tint_array<int4, 4>{}; | ||||||
|   *(tint_symbol_4) = src_let; |   *(tint_symbol_4) = src_let; | ||||||
|   *(tint_symbol_4) = src_function; |   *(tint_symbol_4) = src_function; | ||||||
|   *(tint_symbol_4) = *(tint_symbol_5); |   *(tint_symbol_4) = *(tint_symbol_5); | ||||||
| @ -46,7 +43,7 @@ void foo(tint_array_wrapper src_param, threadgroup tint_array_wrapper* const tin | |||||||
|   *(tint_symbol_4) = tint_symbol.arr; |   *(tint_symbol_4) = tint_symbol.arr; | ||||||
|   *(tint_symbol_4) = (*(tint_symbol_7)).arr; |   *(tint_symbol_4) = (*(tint_symbol_7)).arr; | ||||||
|   *(tint_symbol_4) = (*(tint_symbol_8)).arr; |   *(tint_symbol_4) = (*(tint_symbol_8)).arr; | ||||||
|   tint_array_wrapper_1 src_nested = {}; |   tint_array<tint_array<tint_array<int, 2>, 3>, 4> src_nested = {}; | ||||||
|   *(tint_symbol_9) = src_nested; |   *(tint_symbol_9) = src_nested; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,34 +1,35 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   float arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| float f1(tint_array_wrapper a) { | float f1(tint_array<float, 4> a) { | ||||||
|   return a.arr[3]; |   return a[3]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_1 { | float f2(tint_array<tint_array<float, 4>, 3> a) { | ||||||
|   tint_array_wrapper arr[3]; |   return a[2][3]; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| float f2(tint_array_wrapper_1 a) { |  | ||||||
|   return a.arr[2].arr[3]; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_2 { | float f3(tint_array<tint_array<tint_array<float, 4>, 3>, 2> a) { | ||||||
|   tint_array_wrapper_1 arr[2]; |   return a[1][2][3]; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| float f3(tint_array_wrapper_2 a) { |  | ||||||
|   return a.arr[1].arr[2].arr[3]; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol() { | kernel void tint_symbol() { | ||||||
|   tint_array_wrapper const a1 = {.arr={}}; |   tint_array<float, 4> const a1 = tint_array<float, 4>{}; | ||||||
|   tint_array_wrapper_1 const a2 = {.arr={}}; |   tint_array<tint_array<float, 4>, 3> const a2 = tint_array<tint_array<float, 4>, 3>{}; | ||||||
|   tint_array_wrapper_2 const a3 = {.arr={}}; |   tint_array<tint_array<tint_array<float, 4>, 3>, 2> const a3 = tint_array<tint_array<tint_array<float, 4>, 3>, 2>{}; | ||||||
|   float const v1 = f1(a1); |   float const v1 = f1(a1); | ||||||
|   float const v2 = f2(a2); |   float const v2 = f2(a2); | ||||||
|   float const v3 = f3(a3); |   float const v3 = f3(a3); | ||||||
|  | |||||||
| @ -1,42 +1,43 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   float arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| tint_array_wrapper f1() { | tint_array<float, 4> f1() { | ||||||
|   tint_array_wrapper const tint_symbol_6 = {.arr={}}; |   tint_array<float, 4> const tint_symbol_6 = tint_array<float, 4>{}; | ||||||
|   return tint_symbol_6; |   return tint_symbol_6; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_1 { | tint_array<tint_array<float, 4>, 3> f2() { | ||||||
|   tint_array_wrapper arr[3]; |   tint_array<float, 4> const tint_symbol_1 = f1(); | ||||||
| }; |   tint_array<float, 4> const tint_symbol_2 = f1(); | ||||||
| 
 |   tint_array<float, 4> const tint_symbol_3 = f1(); | ||||||
| tint_array_wrapper_1 f2() { |   tint_array<tint_array<float, 4>, 3> const tint_symbol_7 = tint_array<tint_array<float, 4>, 3>{tint_symbol_1, tint_symbol_2, tint_symbol_3}; | ||||||
|   tint_array_wrapper const tint_symbol_1 = f1(); |  | ||||||
|   tint_array_wrapper const tint_symbol_2 = f1(); |  | ||||||
|   tint_array_wrapper const tint_symbol_3 = f1(); |  | ||||||
|   tint_array_wrapper_1 const tint_symbol_7 = {.arr={tint_symbol_1, tint_symbol_2, tint_symbol_3}}; |  | ||||||
|   return tint_symbol_7; |   return tint_symbol_7; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_2 { | tint_array<tint_array<tint_array<float, 4>, 3>, 2> f3() { | ||||||
|   tint_array_wrapper_1 arr[2]; |   tint_array<tint_array<float, 4>, 3> const tint_symbol_4 = f2(); | ||||||
| }; |   tint_array<tint_array<float, 4>, 3> const tint_symbol_5 = f2(); | ||||||
| 
 |   tint_array<tint_array<tint_array<float, 4>, 3>, 2> const tint_symbol_8 = tint_array<tint_array<tint_array<float, 4>, 3>, 2>{tint_symbol_4, tint_symbol_5}; | ||||||
| tint_array_wrapper_2 f3() { |  | ||||||
|   tint_array_wrapper_1 const tint_symbol_4 = f2(); |  | ||||||
|   tint_array_wrapper_1 const tint_symbol_5 = f2(); |  | ||||||
|   tint_array_wrapper_2 const tint_symbol_8 = {.arr={tint_symbol_4, tint_symbol_5}}; |  | ||||||
|   return tint_symbol_8; |   return tint_symbol_8; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol() { | kernel void tint_symbol() { | ||||||
|   tint_array_wrapper const a1 = f1(); |   tint_array<float, 4> const a1 = f1(); | ||||||
|   tint_array_wrapper_1 const a2 = f2(); |   tint_array<tint_array<float, 4>, 3> const a2 = f2(); | ||||||
|   tint_array_wrapper_2 const a3 = f3(); |   tint_array<tint_array<tint_array<float, 4>, 3>, 2> const a3 = f3(); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,19 +1,28 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| constant int slen = 4; | constant int slen = 4; | ||||||
| 
 | 
 | ||||||
| constant uint ulen = 4u; | constant uint ulen = 4u; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   float arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| fragment void tint_symbol() { | fragment void tint_symbol() { | ||||||
|   tint_array_wrapper signed_literal = {}; |   tint_array<float, 4> signed_literal = {}; | ||||||
|   tint_array_wrapper unsigned_literal = {}; |   tint_array<float, 4> unsigned_literal = {}; | ||||||
|   tint_array_wrapper signed_constant = {}; |   tint_array<float, 4> signed_constant = {}; | ||||||
|   tint_array_wrapper unsigned_constant = {}; |   tint_array<float, 4> unsigned_constant = {}; | ||||||
|   signed_literal = unsigned_constant; |   signed_literal = unsigned_constant; | ||||||
|   signed_constant = unsigned_literal; |   signed_constant = unsigned_literal; | ||||||
|   return; |   return; | ||||||
|  | |||||||
| @ -1,40 +1,41 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct strided_arr { | struct strided_arr { | ||||||
|   /* 0x0000 */ float el; |   /* 0x0000 */ float el; | ||||||
|   /* 0x0004 */ int8_t tint_pad[4]; |   /* 0x0004 */ tint_array<int8_t, 4> tint_pad; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ strided_arr arr[2]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   /* 0x0000 */ tint_array_wrapper arr[3]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct strided_arr_1 { | struct strided_arr_1 { | ||||||
|   /* 0x0000 */ tint_array_wrapper_1 el; |   /* 0x0000 */ tint_array<tint_array<strided_arr, 2>, 3> el; | ||||||
|   /* 0x0030 */ int8_t tint_pad_1[80]; |   /* 0x0030 */ tint_array<int8_t, 80> tint_pad_1; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   /* 0x0000 */ strided_arr_1 arr[4]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ tint_array_wrapper_2 a; |   /* 0x0000 */ tint_array<strided_arr_1, 4> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void f_1(device S* const tint_symbol_1) { | void f_1(device S* const tint_symbol_1) { | ||||||
|   tint_array_wrapper_2 const x_19 = (*(tint_symbol_1)).a; |   tint_array<strided_arr_1, 4> const x_19 = (*(tint_symbol_1)).a; | ||||||
|   tint_array_wrapper_1 const x_24 = (*(tint_symbol_1)).a.arr[3].el; |   tint_array<tint_array<strided_arr, 2>, 3> const x_24 = (*(tint_symbol_1)).a[3].el; | ||||||
|   tint_array_wrapper const x_28 = (*(tint_symbol_1)).a.arr[3].el.arr[2]; |   tint_array<strided_arr, 2> const x_28 = (*(tint_symbol_1)).a[3].el[2]; | ||||||
|   float const x_32 = (*(tint_symbol_1)).a.arr[3].el.arr[2].arr[1].el; |   float const x_32 = (*(tint_symbol_1)).a[3].el[2][1].el; | ||||||
|   tint_array_wrapper_2 const tint_symbol = {.arr={}}; |   tint_array<strided_arr_1, 4> const tint_symbol = tint_array<strided_arr_1, 4>{}; | ||||||
|   (*(tint_symbol_1)).a = tint_symbol; |   (*(tint_symbol_1)).a = tint_symbol; | ||||||
|   (*(tint_symbol_1)).a.arr[3].el.arr[2].arr[1].el = 5.0f; |   (*(tint_symbol_1)).a[3].el[2][1].el = 5.0f; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,56 +1,53 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[4]; |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_2 { | template<typename T, size_t N> | ||||||
|   tint_array_wrapper arr[3]; | struct tint_array { | ||||||
| }; |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
| 
 |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
| struct tint_array_wrapper_1 { |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|   tint_array_wrapper_2 arr[2]; |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
| }; |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
| 
 |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
| struct tint_array_wrapper_3 { |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|   tint_array_wrapper arr[2]; |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol() { | kernel void tint_symbol() { | ||||||
|   int const x = 42; |   int const x = 42; | ||||||
|   tint_array_wrapper const empty = {.arr={}}; |   tint_array<int, 4> const empty = tint_array<int, 4>{}; | ||||||
|   tint_array_wrapper const nonempty = {.arr={1, 2, 3, 4}}; |   tint_array<int, 4> const nonempty = tint_array<int, 4>{1, 2, 3, 4}; | ||||||
|   tint_array_wrapper const nonempty_with_expr = {.arr={1, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1))), nonempty.arr[3]}}; |   tint_array<int, 4> const nonempty_with_expr = tint_array<int, 4>{1, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1))), 4}; | ||||||
|   tint_array_wrapper_1 const nested_empty = {.arr={}}; |   tint_array<tint_array<tint_array<int, 4>, 3>, 2> const nested_empty = tint_array<tint_array<tint_array<int, 4>, 3>, 2>{}; | ||||||
|   tint_array_wrapper const tint_symbol_1 = {.arr={1, 2, 3, 4}}; |   tint_array<int, 4> const tint_symbol_1 = tint_array<int, 4>{1, 2, 3, 4}; | ||||||
|   tint_array_wrapper const tint_symbol_2 = {.arr={5, 6, 7, 8}}; |   tint_array<int, 4> const tint_symbol_2 = tint_array<int, 4>{5, 6, 7, 8}; | ||||||
|   tint_array_wrapper const tint_symbol_3 = {.arr={9, 10, 11, 12}}; |   tint_array<int, 4> const tint_symbol_3 = tint_array<int, 4>{9, 10, 11, 12}; | ||||||
|   tint_array_wrapper_2 const tint_symbol_4 = {.arr={tint_symbol_1, tint_symbol_2, tint_symbol_3}}; |   tint_array<tint_array<int, 4>, 3> const tint_symbol_4 = tint_array<tint_array<int, 4>, 3>{tint_symbol_1, tint_symbol_2, tint_symbol_3}; | ||||||
|   tint_array_wrapper const tint_symbol_5 = {.arr={13, 14, 15, 16}}; |   tint_array<int, 4> const tint_symbol_5 = tint_array<int, 4>{13, 14, 15, 16}; | ||||||
|   tint_array_wrapper const tint_symbol_6 = {.arr={17, 18, 19, 20}}; |   tint_array<int, 4> const tint_symbol_6 = tint_array<int, 4>{17, 18, 19, 20}; | ||||||
|   tint_array_wrapper const tint_symbol_7 = {.arr={21, 22, 23, 24}}; |   tint_array<int, 4> const tint_symbol_7 = tint_array<int, 4>{21, 22, 23, 24}; | ||||||
|   tint_array_wrapper_2 const tint_symbol_8 = {.arr={tint_symbol_5, tint_symbol_6, tint_symbol_7}}; |   tint_array<tint_array<int, 4>, 3> const tint_symbol_8 = tint_array<tint_array<int, 4>, 3>{tint_symbol_5, tint_symbol_6, tint_symbol_7}; | ||||||
|   tint_array_wrapper_1 const nested_nonempty = {.arr={tint_symbol_4, tint_symbol_8}}; |   tint_array<tint_array<tint_array<int, 4>, 3>, 2> const nested_nonempty = tint_array<tint_array<tint_array<int, 4>, 3>, 2>{tint_symbol_4, tint_symbol_8}; | ||||||
|   tint_array_wrapper const tint_symbol_9 = {.arr={1, 2, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1)))}}; |   tint_array<int, 4> const tint_symbol_9 = tint_array<int, 4>{1, 2, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1)))}; | ||||||
|   tint_array_wrapper const tint_symbol_10 = {.arr={5, 6, nonempty.arr[2], as_type<int>((as_type<uint>(nonempty.arr[3]) + as_type<uint>(1)))}}; |   tint_array<int, 4> const tint_symbol_10 = tint_array<int, 4>{5, 6, 3, as_type<int>((as_type<uint>(4) + as_type<uint>(1)))}; | ||||||
|   tint_array_wrapper_2 const tint_symbol_11 = {.arr={tint_symbol_9, tint_symbol_10, nonempty}}; |   tint_array<tint_array<int, 4>, 3> const tint_symbol_11 = tint_array<tint_array<int, 4>, 3>{tint_symbol_9, tint_symbol_10, nonempty}; | ||||||
|   tint_array_wrapper_1 const nested_nonempty_with_expr = {.arr={tint_symbol_11, nested_nonempty.arr[1]}}; |   tint_array<tint_array<tint_array<int, 4>, 3>, 2> const nested_nonempty_with_expr = tint_array<tint_array<tint_array<int, 4>, 3>, 2>{tint_symbol_11, nested_nonempty[1]}; | ||||||
|   tint_array_wrapper const tint_symbol_12 = {.arr={}}; |   tint_array<int, 4> const tint_symbol_12 = tint_array<int, 4>{}; | ||||||
|   int const subexpr_empty = tint_symbol_12.arr[1]; |   int const subexpr_empty = 0; | ||||||
|   tint_array_wrapper const tint_symbol_13 = {.arr={1, 2, 3, 4}}; |   tint_array<int, 4> const tint_symbol_13 = tint_array<int, 4>{1, 2, 3, 4}; | ||||||
|   int const subexpr_nonempty = tint_symbol_13.arr[2]; |   int const subexpr_nonempty = 3; | ||||||
|   tint_array_wrapper const tint_symbol_14 = {.arr={1, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1))), nonempty.arr[3]}}; |   tint_array<int, 4> const tint_symbol_14 = tint_array<int, 4>{1, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1))), 4}; | ||||||
|   int const subexpr_nonempty_with_expr = tint_symbol_14.arr[2]; |   int const subexpr_nonempty_with_expr = tint_symbol_14[2]; | ||||||
|   tint_array_wrapper_3 const tint_symbol_15 = {.arr={}}; |   tint_array<tint_array<int, 4>, 2> const tint_symbol_15 = tint_array<tint_array<int, 4>, 2>{}; | ||||||
|   tint_array_wrapper const subexpr_nested_empty = tint_symbol_15.arr[1]; |   tint_array<int, 4> const subexpr_nested_empty = tint_symbol_15[1]; | ||||||
|   tint_array_wrapper const tint_symbol_16 = {.arr={1, 2, 3, 4}}; |   tint_array<int, 4> const tint_symbol_16 = tint_array<int, 4>{1, 2, 3, 4}; | ||||||
|   tint_array_wrapper const tint_symbol_17 = {.arr={5, 6, 7, 8}}; |   tint_array<int, 4> const tint_symbol_17 = tint_array<int, 4>{5, 6, 7, 8}; | ||||||
|   tint_array_wrapper_3 const tint_symbol_18 = {.arr={tint_symbol_16, tint_symbol_17}}; |   tint_array<tint_array<int, 4>, 2> const tint_symbol_18 = tint_array<tint_array<int, 4>, 2>{tint_symbol_16, tint_symbol_17}; | ||||||
|   tint_array_wrapper const subexpr_nested_nonempty = tint_symbol_18.arr[1]; |   tint_array<int, 4> const subexpr_nested_nonempty = tint_symbol_18[1]; | ||||||
|   tint_array_wrapper const tint_symbol_19 = {.arr={1, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1))), nonempty.arr[3]}}; |   tint_array<int, 4> const tint_symbol_19 = tint_array<int, 4>{1, 42, as_type<int>((as_type<uint>(42) + as_type<uint>(1))), 4}; | ||||||
|   tint_array_wrapper_3 const tint_symbol_20 = {.arr={tint_symbol_19, nested_nonempty.arr[1].arr[2]}}; |   tint_array<tint_array<int, 4>, 2> const tint_symbol_20 = tint_array<tint_array<int, 4>, 2>{tint_symbol_19, nested_nonempty[1][2]}; | ||||||
|   tint_array_wrapper const subexpr_nested_nonempty_with_expr = tint_symbol_20.arr[1]; |   tint_array<int, 4> const subexpr_nested_nonempty_with_expr = tint_symbol_20[1]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,8 +12,16 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { | template<typename T, size_t N> | ||||||
|   /* 0x0000 */ int4 arr[4]; | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Inner { | struct Inner { | ||||||
| @ -25,12 +33,12 @@ struct Inner { | |||||||
|   /* 0x002c */ float f; |   /* 0x002c */ float f; | ||||||
|   /* 0x0030 */ float2x3 g; |   /* 0x0030 */ float2x3 g; | ||||||
|   /* 0x0050 */ float3x2 h; |   /* 0x0050 */ float3x2 h; | ||||||
|   /* 0x0068 */ int8_t tint_pad[8]; |   /* 0x0068 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0070 */ tint_array_wrapper i; |   /* 0x0070 */ tint_array<int4, 4> i; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ Inner arr[1]; |   /* 0x0000 */ tint_array<Inner, 1> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void tint_symbol_inner(uint idx, const device S* const tint_symbol_1) { | void tint_symbol_inner(uint idx, const device S* const tint_symbol_1) { | ||||||
| @ -42,7 +50,7 @@ void tint_symbol_inner(uint idx, const device S* const tint_symbol_1) { | |||||||
|   float const f = (*(tint_symbol_1)).arr[idx].f; |   float const f = (*(tint_symbol_1)).arr[idx].f; | ||||||
|   float2x3 const g = (*(tint_symbol_1)).arr[idx].g; |   float2x3 const g = (*(tint_symbol_1)).arr[idx].g; | ||||||
|   float3x2 const h = (*(tint_symbol_1)).arr[idx].h; |   float3x2 const h = (*(tint_symbol_1)).arr[idx].h; | ||||||
|   tint_array_wrapper const i = (*(tint_symbol_1)).arr[idx].i; |   tint_array<int4, 4> const i = (*(tint_symbol_1)).arr[idx].i; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const device S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) { | kernel void tint_symbol(const device S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) { | ||||||
|  | |||||||
| @ -12,8 +12,16 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { | template<typename T, size_t N> | ||||||
|   /* 0x0000 */ int4 arr[4]; | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Inner { | struct Inner { | ||||||
| @ -25,12 +33,12 @@ struct Inner { | |||||||
|   /* 0x002c */ float f; |   /* 0x002c */ float f; | ||||||
|   /* 0x0030 */ float2x3 g; |   /* 0x0030 */ float2x3 g; | ||||||
|   /* 0x0050 */ float3x2 h; |   /* 0x0050 */ float3x2 h; | ||||||
|   /* 0x0068 */ int8_t tint_pad[8]; |   /* 0x0068 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0070 */ tint_array_wrapper i; |   /* 0x0070 */ tint_array<int4, 4> i; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ Inner arr[1]; |   /* 0x0000 */ tint_array<Inner, 1> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void tint_symbol_inner(uint idx, device S* const tint_symbol_2) { | void tint_symbol_inner(uint idx, device S* const tint_symbol_2) { | ||||||
| @ -42,7 +50,7 @@ void tint_symbol_inner(uint idx, device S* const tint_symbol_2) { | |||||||
|   (*(tint_symbol_2)).arr[idx].f = 0.0f; |   (*(tint_symbol_2)).arr[idx].f = 0.0f; | ||||||
|   (*(tint_symbol_2)).arr[idx].g = float2x3(float3(0.0f), float3(0.0f)); |   (*(tint_symbol_2)).arr[idx].g = float2x3(float3(0.0f), float3(0.0f)); | ||||||
|   (*(tint_symbol_2)).arr[idx].h = float3x2(float2(0.0f), float2(0.0f), float2(0.0f)); |   (*(tint_symbol_2)).arr[idx].h = float3x2(float2(0.0f), float2(0.0f), float2(0.0f)); | ||||||
|   tint_array_wrapper const tint_symbol_1 = {.arr={}}; |   tint_array<int4, 4> const tint_symbol_1 = tint_array<int4, 4>{}; | ||||||
|   (*(tint_symbol_2)).arr[idx].i = tint_symbol_1; |   (*(tint_symbol_2)).arr[idx].i = tint_symbol_1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,12 +12,20 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct Inner { | template<typename T, size_t N> | ||||||
|   /* 0x0000 */ int x; | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { | struct Inner { | ||||||
|   /* 0x0000 */ Inner arr[4]; |   /* 0x0000 */ int x; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
| @ -30,8 +38,8 @@ struct S { | |||||||
|   /* 0x0030 */ float2x3 g; |   /* 0x0030 */ float2x3 g; | ||||||
|   /* 0x0050 */ float3x2 h; |   /* 0x0050 */ float3x2 h; | ||||||
|   /* 0x0068 */ Inner i; |   /* 0x0068 */ Inner i; | ||||||
|   /* 0x006c */ tint_array_wrapper j; |   /* 0x006c */ tint_array<Inner, 4> j; | ||||||
|   /* 0x007c */ int8_t tint_pad[4]; |   /* 0x007c */ tint_array<int8_t, 4> tint_pad; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(0)]]) { | kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(0)]]) { | ||||||
| @ -44,7 +52,7 @@ kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(0)]]) { | |||||||
|   float2x3 const g = (*(tint_symbol_1)).g; |   float2x3 const g = (*(tint_symbol_1)).g; | ||||||
|   float3x2 const h = (*(tint_symbol_1)).h; |   float3x2 const h = (*(tint_symbol_1)).h; | ||||||
|   Inner const i = (*(tint_symbol_1)).i; |   Inner const i = (*(tint_symbol_1)).i; | ||||||
|   tint_array_wrapper const j = (*(tint_symbol_1)).j; |   tint_array<Inner, 4> const j = (*(tint_symbol_1)).j; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,12 +12,20 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct Inner { | template<typename T, size_t N> | ||||||
|   /* 0x0000 */ int x; | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { | struct Inner { | ||||||
|   /* 0x0000 */ Inner arr[4]; |   /* 0x0000 */ int x; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
| @ -30,8 +38,8 @@ struct S { | |||||||
|   /* 0x0030 */ float2x3 g; |   /* 0x0030 */ float2x3 g; | ||||||
|   /* 0x0050 */ float3x2 h; |   /* 0x0050 */ float3x2 h; | ||||||
|   /* 0x0068 */ Inner i; |   /* 0x0068 */ Inner i; | ||||||
|   /* 0x006c */ tint_array_wrapper j; |   /* 0x006c */ tint_array<Inner, 4> j; | ||||||
|   /* 0x007c */ int8_t tint_pad[4]; |   /* 0x007c */ tint_array<int8_t, 4> tint_pad; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(device S* tint_symbol_3 [[buffer(0)]]) { | kernel void tint_symbol(device S* tint_symbol_3 [[buffer(0)]]) { | ||||||
| @ -45,7 +53,7 @@ kernel void tint_symbol(device S* tint_symbol_3 [[buffer(0)]]) { | |||||||
|   (*(tint_symbol_3)).h = float3x2(float2(0.0f), float2(0.0f), float2(0.0f)); |   (*(tint_symbol_3)).h = float3x2(float2(0.0f), float2(0.0f), float2(0.0f)); | ||||||
|   Inner const tint_symbol_1 = {}; |   Inner const tint_symbol_1 = {}; | ||||||
|   (*(tint_symbol_3)).i = tint_symbol_1; |   (*(tint_symbol_3)).i = tint_symbol_1; | ||||||
|   tint_array_wrapper const tint_symbol_2 = {.arr={}}; |   tint_array<Inner, 4> const tint_symbol_2 = tint_array<Inner, 4>{}; | ||||||
|   (*(tint_symbol_3)).j = tint_symbol_2; |   (*(tint_symbol_3)).j = tint_symbol_2; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,11 +1,20 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ float arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(device tint_array_wrapper* tint_symbol_1 [[buffer(0)]], const device tint_array_wrapper* tint_symbol_2 [[buffer(1)]]) { | kernel void tint_symbol(device tint_array<float, 4>* tint_symbol_1 [[buffer(0)]], const device tint_array<float, 4>* tint_symbol_2 [[buffer(1)]]) { | ||||||
|   *(tint_symbol_1) = *(tint_symbol_2); |   *(tint_symbol_1) = *(tint_symbol_2); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,16 +1,29 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ float f; |   /* 0x0000 */ float f; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_symbol_2 { | struct tint_symbol_2 { | ||||||
|   /* 0x0000 */ S arr[1]; |   /* 0x0000 */ tint_array<S, 1> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_symbol_4 { | struct tint_symbol_4 { | ||||||
|   /* 0x0000 */ S arr[1]; |   /* 0x0000 */ tint_array<S, 1> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(device tint_symbol_2* tint_symbol_1 [[buffer(0)]], const device tint_symbol_4* tint_symbol_3 [[buffer(1)]]) { | kernel void tint_symbol(device tint_symbol_2* tint_symbol_1 [[buffer(0)]], const device tint_symbol_4* tint_symbol_3 [[buffer(1)]]) { | ||||||
|  | |||||||
| @ -12,8 +12,16 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { | template<typename T, size_t N> | ||||||
|   /* 0x0000 */ int4 arr[4]; | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Inner { | struct Inner { | ||||||
| @ -27,30 +35,26 @@ struct Inner { | |||||||
|   /* 0x0038 */ int2 h; |   /* 0x0038 */ int2 h; | ||||||
|   /* 0x0040 */ float2x3 i; |   /* 0x0040 */ float2x3 i; | ||||||
|   /* 0x0060 */ float3x2 j; |   /* 0x0060 */ float3x2 j; | ||||||
|   /* 0x0078 */ int8_t tint_pad[8]; |   /* 0x0078 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0080 */ tint_array_wrapper k; |   /* 0x0080 */ tint_array<int4, 4> k; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   /* 0x0000 */ Inner arr[8]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   /* 0x0000 */ tint_array_wrapper_1 arr; |   /* 0x0000 */ tint_array<Inner, 8> arr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void tint_symbol_inner(uint idx, const constant S* const tint_symbol_1) { | void tint_symbol_inner(uint idx, const constant S* const tint_symbol_1) { | ||||||
|   int3 const a = (*(tint_symbol_1)).arr.arr[idx].a; |   int3 const a = (*(tint_symbol_1)).arr[idx].a; | ||||||
|   int const b = (*(tint_symbol_1)).arr.arr[idx].b; |   int const b = (*(tint_symbol_1)).arr[idx].b; | ||||||
|   uint3 const c = (*(tint_symbol_1)).arr.arr[idx].c; |   uint3 const c = (*(tint_symbol_1)).arr[idx].c; | ||||||
|   uint const d = (*(tint_symbol_1)).arr.arr[idx].d; |   uint const d = (*(tint_symbol_1)).arr[idx].d; | ||||||
|   float3 const e = (*(tint_symbol_1)).arr.arr[idx].e; |   float3 const e = (*(tint_symbol_1)).arr[idx].e; | ||||||
|   float const f = (*(tint_symbol_1)).arr.arr[idx].f; |   float const f = (*(tint_symbol_1)).arr[idx].f; | ||||||
|   int2 const g = (*(tint_symbol_1)).arr.arr[idx].g; |   int2 const g = (*(tint_symbol_1)).arr[idx].g; | ||||||
|   int2 const h = (*(tint_symbol_1)).arr.arr[idx].h; |   int2 const h = (*(tint_symbol_1)).arr[idx].h; | ||||||
|   float2x3 const i = (*(tint_symbol_1)).arr.arr[idx].i; |   float2x3 const i = (*(tint_symbol_1)).arr[idx].i; | ||||||
|   float3x2 const j = (*(tint_symbol_1)).arr.arr[idx].j; |   float3x2 const j = (*(tint_symbol_1)).arr[idx].j; | ||||||
|   tint_array_wrapper const k = (*(tint_symbol_1)).arr.arr[idx].k; |   tint_array<int4, 4> const k = (*(tint_symbol_1)).arr[idx].k; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) { | kernel void tint_symbol(const constant S* tint_symbol_2 [[buffer(0)]], uint idx [[thread_index_in_threadgroup]]) { | ||||||
|  | |||||||
| @ -2,6 +2,18 @@ | |||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| 
 | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| template<typename T, int N, int M> | template<typename T, int N, int M> | ||||||
| inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | ||||||
|   return lhs * vec<T, N>(rhs); |   return lhs * vec<T, N>(rhs); | ||||||
| @ -14,11 +26,7 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
| 
 | 
 | ||||||
| struct Inner { | struct Inner { | ||||||
|   /* 0x0000 */ int x; |   /* 0x0000 */ int x; | ||||||
|   /* 0x0004 */ int8_t tint_pad[12]; |   /* 0x0004 */ tint_array<int8_t, 12> tint_pad; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ Inner arr[4]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
| @ -32,9 +40,9 @@ struct S { | |||||||
|   /* 0x0038 */ int2 h; |   /* 0x0038 */ int2 h; | ||||||
|   /* 0x0040 */ float2x3 i; |   /* 0x0040 */ float2x3 i; | ||||||
|   /* 0x0060 */ float3x2 j; |   /* 0x0060 */ float3x2 j; | ||||||
|   /* 0x0078 */ int8_t tint_pad_1[8]; |   /* 0x0078 */ tint_array<int8_t, 8> tint_pad_1; | ||||||
|   /* 0x0080 */ Inner k; |   /* 0x0080 */ Inner k; | ||||||
|   /* 0x0090 */ tint_array_wrapper l; |   /* 0x0090 */ tint_array<Inner, 4> l; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) { | kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) { | ||||||
| @ -49,7 +57,7 @@ kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) { | |||||||
|   float2x3 const i = (*(tint_symbol_1)).i; |   float2x3 const i = (*(tint_symbol_1)).i; | ||||||
|   float3x2 const j = (*(tint_symbol_1)).j; |   float3x2 const j = (*(tint_symbol_1)).j; | ||||||
|   Inner const k = (*(tint_symbol_1)).k; |   Inner const k = (*(tint_symbol_1)).k; | ||||||
|   tint_array_wrapper const l = (*(tint_symbol_1)).l; |   tint_array<Inner, 4> const l = (*(tint_symbol_1)).l; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,21 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ float4 arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_array_wrapper* tint_symbol_1 [[buffer(0)]]) { | kernel void tint_symbol(const constant tint_array<float4, 4>* tint_symbol_1 [[buffer(0)]]) { | ||||||
|   tint_array_wrapper const x = *(tint_symbol_1); |   tint_array<float4, 4> const x = *(tint_symbol_1); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,6 +12,18 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| void marg8uintin() { | void marg8uintin() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -21,9 +33,9 @@ struct Uniforms { | |||||||
|   /* 0x0008 */ uint puuuuuuuuuuuuuuuuad1; |   /* 0x0008 */ uint puuuuuuuuuuuuuuuuad1; | ||||||
|   /* 0x000c */ uint pad2; |   /* 0x000c */ uint pad2; | ||||||
|   /* 0x0010 */ packed_float3 bbMin; |   /* 0x0010 */ packed_float3 bbMin; | ||||||
|   /* 0x001c */ int8_t tint_pad[4]; |   /* 0x001c */ tint_array<int8_t, 4> tint_pad; | ||||||
|   /* 0x0020 */ packed_float3 bbMax; |   /* 0x0020 */ packed_float3 bbMax; | ||||||
|   /* 0x002c */ int8_t tint_pad_1[4]; |   /* 0x002c */ tint_array<int8_t, 4> tint_pad_1; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Dbg { | struct Dbg { | ||||||
| @ -42,23 +54,23 @@ struct Dbg { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct F32s { | struct F32s { | ||||||
|   /* 0x0000 */ float values[1]; |   /* 0x0000 */ tint_array<float, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct U32s { | struct U32s { | ||||||
|   /* 0x0000 */ uint values[1]; |   /* 0x0000 */ tint_array<uint, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct I32s { | struct I32s { | ||||||
|   int values[1]; |   tint_array<int, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct AU32s { | struct AU32s { | ||||||
|   /* 0x0000 */ atomic_uint values[1]; |   /* 0x0000 */ tint_array<atomic_uint, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct AI32s { | struct AI32s { | ||||||
|   /* 0x0000 */ atomic_int values[1]; |   /* 0x0000 */ tint_array<atomic_int, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| float3 toVoxelPos(float3 position, const constant Uniforms* const tint_symbol) { | float3 toVoxelPos(float3 position, const constant Uniforms* const tint_symbol) { | ||||||
|  | |||||||
| @ -1,8 +1,21 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|  | |||||||
| @ -13,6 +13,19 @@ bug/dawn/947.wgsl:55:33 note: reading from user-defined input 'texcoord' may res | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|   /* 0x0000 */ float2 u_scale; |   /* 0x0000 */ float2 u_scale; | ||||||
|   /* 0x0008 */ float2 u_offset; |   /* 0x0008 */ float2 u_offset; | ||||||
| @ -28,19 +41,15 @@ struct tint_symbol { | |||||||
|   float4 position [[position]]; |   float4 position [[position]]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   float2 arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| VertexOutputs vs_main_inner(uint VertexIndex, const constant Uniforms* const tint_symbol_5) { | VertexOutputs vs_main_inner(uint VertexIndex, const constant Uniforms* const tint_symbol_5) { | ||||||
|   tint_array_wrapper texcoord = {.arr={float2(-0.5f, 0.0f), float2(1.5f, 0.0f), float2(0.5f, 2.0f)}}; |   tint_array<float2, 3> texcoord = tint_array<float2, 3>{float2(-0.5f, 0.0f), float2(1.5f, 0.0f), float2(0.5f, 2.0f)}; | ||||||
|   VertexOutputs output = {}; |   VertexOutputs output = {}; | ||||||
|   output.position = float4(((texcoord.arr[VertexIndex] * 2.0f) - float2(1.0f)), 0.0f, 1.0f); |   output.position = float4(((texcoord[VertexIndex] * 2.0f) - float2(1.0f)), 0.0f, 1.0f); | ||||||
|   bool flipY = ((*(tint_symbol_5)).u_scale[1] < 0.0f); |   bool flipY = ((*(tint_symbol_5)).u_scale[1] < 0.0f); | ||||||
|   if (flipY) { |   if (flipY) { | ||||||
|     output.texcoords = ((((texcoord.arr[VertexIndex] * (*(tint_symbol_5)).u_scale) + (*(tint_symbol_5)).u_offset) * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)); |     output.texcoords = ((((texcoord[VertexIndex] * (*(tint_symbol_5)).u_scale) + (*(tint_symbol_5)).u_offset) * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)); | ||||||
|   } else { |   } else { | ||||||
|     output.texcoords = ((((texcoord.arr[VertexIndex] * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)) * (*(tint_symbol_5)).u_scale) + (*(tint_symbol_5)).u_offset); |     output.texcoords = ((((texcoord[VertexIndex] * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)) * (*(tint_symbol_5)).u_scale) + (*(tint_symbol_5)).u_offset); | ||||||
|   } |   } | ||||||
|   return output; |   return output; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -19,7 +28,7 @@ struct Result { | |||||||
| 
 | 
 | ||||||
| kernel void f(device Result* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_1 [[buffer(0)]]) { | kernel void f(device Result* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_1 [[buffer(0)]]) { | ||||||
|   S s = {}; |   S s = {}; | ||||||
|   (*(tint_symbol)).out = s.data.arr[(*(tint_symbol_1)).dynamic_idx]; |   (*(tint_symbol)).out = s.data[(*(tint_symbol_1)).dynamic_idx]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -19,7 +28,7 @@ struct Result { | |||||||
| 
 | 
 | ||||||
| kernel void f(device Result* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_2 [[buffer(0)]]) { | kernel void f(device Result* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_2 [[buffer(0)]]) { | ||||||
|   thread S tint_symbol_1 = {}; |   thread S tint_symbol_1 = {}; | ||||||
|   (*(tint_symbol)).out = tint_symbol_1.data.arr[(*(tint_symbol_2)).dynamic_idx]; |   (*(tint_symbol)).out = tint_symbol_1.data[(*(tint_symbol_2)).dynamic_idx]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| @ -9,16 +22,12 @@ struct Result { | |||||||
|   /* 0x0000 */ int out; |   /* 0x0000 */ int out; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ int arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct SSBO { | struct SSBO { | ||||||
|   /* 0x0000 */ tint_array_wrapper data; |   /* 0x0000 */ tint_array<int, 4> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void f(device Result* tint_symbol [[buffer(1)]], device SSBO* tint_symbol_1 [[buffer(2)]], const constant UBO* tint_symbol_2 [[buffer(0)]]) { | kernel void f(device Result* tint_symbol [[buffer(1)]], device SSBO* tint_symbol_1 [[buffer(2)]], const constant UBO* tint_symbol_2 [[buffer(0)]]) { | ||||||
|   (*(tint_symbol)).out = (*(tint_symbol_1)).data.arr[(*(tint_symbol_2)).dynamic_idx]; |   (*(tint_symbol)).out = (*(tint_symbol_1)).data[(*(tint_symbol_2)).dynamic_idx]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,14 +1,23 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ int4 arr[4]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ tint_array_wrapper data; |   /* 0x0000 */ tint_array<int4, 4> data; | ||||||
|   /* 0x0040 */ int dynamic_idx; |   /* 0x0040 */ int dynamic_idx; | ||||||
|   /* 0x0044 */ int8_t tint_pad[12]; |   /* 0x0044 */ tint_array<int8_t, 12> tint_pad; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -16,7 +25,7 @@ struct Result { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void f(device Result* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_1 [[buffer(0)]]) { | kernel void f(device Result* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_1 [[buffer(0)]]) { | ||||||
|   (*(tint_symbol)).out = (*(tint_symbol_1)).data.arr[(*(tint_symbol_1)).dynamic_idx][0]; |   (*(tint_symbol)).out = (*(tint_symbol_1)).data[(*(tint_symbol_1)).dynamic_idx][0]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -20,10 +29,10 @@ struct Result { | |||||||
| void f_inner(uint local_invocation_index, threadgroup S* const tint_symbol, device Result* const tint_symbol_1, const constant UBO* const tint_symbol_2) { | void f_inner(uint local_invocation_index, threadgroup S* const tint_symbol, device Result* const tint_symbol_1, const constant UBO* const tint_symbol_2) { | ||||||
|   for(uint idx = local_invocation_index; (idx < 64u); idx = (idx + 1u)) { |   for(uint idx = local_invocation_index; (idx < 64u); idx = (idx + 1u)) { | ||||||
|     uint const i = idx; |     uint const i = idx; | ||||||
|     (*(tint_symbol)).data.arr[i] = 0; |     (*(tint_symbol)).data[i] = 0; | ||||||
|   } |   } | ||||||
|   threadgroup_barrier(mem_flags::mem_threadgroup); |   threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
|   (*(tint_symbol_1)).out = (*(tint_symbol)).data.arr[(*(tint_symbol_2)).dynamic_idx]; |   (*(tint_symbol_1)).out = (*(tint_symbol)).data[(*(tint_symbol_2)).dynamic_idx]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void f(device Result* tint_symbol_4 [[buffer(1)]], const constant UBO* tint_symbol_5 [[buffer(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | kernel void f(device Result* tint_symbol_4 [[buffer(1)]], const constant UBO* tint_symbol_5 [[buffer(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -19,8 +28,8 @@ struct Result { | |||||||
| 
 | 
 | ||||||
| kernel void f(const constant UBO* tint_symbol [[buffer(0)]], device Result* tint_symbol_1 [[buffer(1)]]) { | kernel void f(const constant UBO* tint_symbol [[buffer(0)]], device Result* tint_symbol_1 [[buffer(1)]]) { | ||||||
|   S s = {}; |   S s = {}; | ||||||
|   s.data.arr[(*(tint_symbol)).dynamic_idx] = 1; |   s.data[(*(tint_symbol)).dynamic_idx] = 1; | ||||||
|   (*(tint_symbol_1)).out = s.data.arr[3]; |   (*(tint_symbol_1)).out = s.data[3]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -18,13 +27,13 @@ struct Result { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void x(thread S* const p, const constant UBO* const tint_symbol) { | void x(thread S* const p, const constant UBO* const tint_symbol) { | ||||||
|   (*(p)).data.arr[(*(tint_symbol)).dynamic_idx] = 1; |   (*(p)).data[(*(tint_symbol)).dynamic_idx] = 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void f(const constant UBO* tint_symbol_1 [[buffer(0)]], device Result* tint_symbol_2 [[buffer(1)]]) { | kernel void f(const constant UBO* tint_symbol_1 [[buffer(0)]], device Result* tint_symbol_2 [[buffer(1)]]) { | ||||||
|   S s = {}; |   S s = {}; | ||||||
|   x(&(s), tint_symbol_1); |   x(&(s), tint_symbol_1); | ||||||
|   (*(tint_symbol_2)).out = s.data.arr[3]; |   (*(tint_symbol_2)).out = s.data[3]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -19,8 +28,8 @@ struct Result { | |||||||
| 
 | 
 | ||||||
| kernel void f(const constant UBO* tint_symbol_1 [[buffer(0)]], device Result* tint_symbol_2 [[buffer(1)]]) { | kernel void f(const constant UBO* tint_symbol_1 [[buffer(0)]], device Result* tint_symbol_2 [[buffer(1)]]) { | ||||||
|   thread S tint_symbol = {}; |   thread S tint_symbol = {}; | ||||||
|   tint_symbol.data.arr[(*(tint_symbol_1)).dynamic_idx] = 1; |   tint_symbol.data[(*(tint_symbol_1)).dynamic_idx] = 1; | ||||||
|   (*(tint_symbol_2)).out = tint_symbol.data.arr[3]; |   (*(tint_symbol_2)).out = tint_symbol.data[3]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -18,13 +27,13 @@ struct Result { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void x(thread S* const p, const constant UBO* const tint_symbol) { | void x(thread S* const p, const constant UBO* const tint_symbol) { | ||||||
|   (*(p)).data.arr[(*(tint_symbol)).dynamic_idx] = 1; |   (*(p)).data[(*(tint_symbol)).dynamic_idx] = 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void f(const constant UBO* tint_symbol_2 [[buffer(0)]], device Result* tint_symbol_3 [[buffer(1)]]) { | kernel void f(const constant UBO* tint_symbol_2 [[buffer(0)]], device Result* tint_symbol_3 [[buffer(1)]]) { | ||||||
|   thread S tint_symbol_1 = {}; |   thread S tint_symbol_1 = {}; | ||||||
|   x(&(tint_symbol_1), tint_symbol_2); |   x(&(tint_symbol_1), tint_symbol_2); | ||||||
|   (*(tint_symbol_3)).out = tint_symbol_1.data.arr[3]; |   (*(tint_symbol_3)).out = tint_symbol_1.data[3]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| @ -9,17 +22,13 @@ struct Result { | |||||||
|   /* 0x0000 */ int out; |   /* 0x0000 */ int out; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ int arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct SSBO { | struct SSBO { | ||||||
|   /* 0x0000 */ tint_array_wrapper data; |   /* 0x0000 */ tint_array<int, 4> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void f(device SSBO* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_1 [[buffer(0)]], device Result* tint_symbol_2 [[buffer(2)]]) { | kernel void f(device SSBO* tint_symbol [[buffer(1)]], const constant UBO* tint_symbol_1 [[buffer(0)]], device Result* tint_symbol_2 [[buffer(2)]]) { | ||||||
|   (*(tint_symbol)).data.arr[(*(tint_symbol_1)).dynamic_idx] = 1; |   (*(tint_symbol)).data[(*(tint_symbol_1)).dynamic_idx] = 1; | ||||||
|   (*(tint_symbol_2)).out = (*(tint_symbol)).data.arr[3]; |   (*(tint_symbol_2)).out = (*(tint_symbol)).data[3]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,16 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UBO { | struct UBO { | ||||||
|   /* 0x0000 */ int dynamic_idx; |   /* 0x0000 */ int dynamic_idx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   int arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<int, 64> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
| @ -20,11 +29,11 @@ struct Result { | |||||||
| void f_inner(uint local_invocation_index, threadgroup S* const tint_symbol, const constant UBO* const tint_symbol_1, device Result* const tint_symbol_2) { | void f_inner(uint local_invocation_index, threadgroup S* const tint_symbol, const constant UBO* const tint_symbol_1, device Result* const tint_symbol_2) { | ||||||
|   for(uint idx = local_invocation_index; (idx < 64u); idx = (idx + 1u)) { |   for(uint idx = local_invocation_index; (idx < 64u); idx = (idx + 1u)) { | ||||||
|     uint const i = idx; |     uint const i = idx; | ||||||
|     (*(tint_symbol)).data.arr[i] = 0; |     (*(tint_symbol)).data[i] = 0; | ||||||
|   } |   } | ||||||
|   threadgroup_barrier(mem_flags::mem_threadgroup); |   threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
|   (*(tint_symbol)).data.arr[(*(tint_symbol_1)).dynamic_idx] = 1; |   (*(tint_symbol)).data[(*(tint_symbol_1)).dynamic_idx] = 1; | ||||||
|   (*(tint_symbol_2)).out = (*(tint_symbol)).data.arr[3]; |   (*(tint_symbol_2)).out = (*(tint_symbol)).data[3]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void f(const constant UBO* tint_symbol_4 [[buffer(0)]], device Result* tint_symbol_5 [[buffer(1)]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | kernel void f(const constant UBO* tint_symbol_4 [[buffer(0)]], device Result* tint_symbol_5 [[buffer(1)]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | ||||||
|  | |||||||
| @ -2,6 +2,18 @@ | |||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| 
 | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| template<typename T, int N, int M> | template<typename T, int N, int M> | ||||||
| inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | ||||||
|   return lhs * vec<T, N>(rhs); |   return lhs * vec<T, N>(rhs); | ||||||
| @ -16,26 +28,22 @@ struct Simulation { | |||||||
|   /* 0x0000 */ uint i; |   /* 0x0000 */ uint i; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ float3 arr[8]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct Particle { | struct Particle { | ||||||
|   /* 0x0000 */ tint_array_wrapper position; |   /* 0x0000 */ tint_array<float3, 8> position; | ||||||
|   /* 0x0080 */ float lifetime; |   /* 0x0080 */ float lifetime; | ||||||
|   /* 0x0084 */ int8_t tint_pad[12]; |   /* 0x0084 */ tint_array<int8_t, 12> tint_pad; | ||||||
|   /* 0x0090 */ float4 color; |   /* 0x0090 */ float4 color; | ||||||
|   /* 0x00a0 */ packed_float3 velocity; |   /* 0x00a0 */ packed_float3 velocity; | ||||||
|   /* 0x00ac */ int8_t tint_pad_1[4]; |   /* 0x00ac */ tint_array<int8_t, 4> tint_pad_1; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Particles { | struct Particles { | ||||||
|   /* 0x0000 */ Particle p[1]; |   /* 0x0000 */ tint_array<Particle, 1> p; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const device Particles* tint_symbol_1 [[buffer(1)]], const constant Simulation* tint_symbol_2 [[buffer(0)]]) { | kernel void tint_symbol(const device Particles* tint_symbol_1 [[buffer(1)]], const constant Simulation* tint_symbol_2 [[buffer(0)]]) { | ||||||
|   Particle particle = (*(tint_symbol_1)).p[0]; |   Particle particle = (*(tint_symbol_1)).p[0]; | ||||||
|   particle.position.arr[(*(tint_symbol_2)).i] = particle.position.arr[(*(tint_symbol_2)).i]; |   particle.position[(*(tint_symbol_2)).i] = particle.position[(*(tint_symbol_2)).i]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct PointLight { | struct PointLight { | ||||||
|   float4 position; |   float4 position; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct PointLights { | struct PointLights { | ||||||
|   PointLight values[1]; |   tint_array<PointLight, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
| @ -14,7 +27,7 @@ struct Uniforms { | |||||||
|   /* 0x0040 */ float4x4 proj; |   /* 0x0040 */ float4x4 proj; | ||||||
|   /* 0x0080 */ uint numPointLights; |   /* 0x0080 */ uint numPointLights; | ||||||
|   /* 0x0084 */ uint color_source; |   /* 0x0084 */ uint color_source; | ||||||
|   /* 0x0088 */ int8_t tint_pad[8]; |   /* 0x0088 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0090 */ float4 color; |   /* 0x0090 */ float4 color; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,25 +1,30 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ float4x4 arr[2]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct strided_arr { | struct strided_arr { | ||||||
|   /* 0x0000 */ float el; |   /* 0x0000 */ float el; | ||||||
|   /* 0x0004 */ int8_t tint_pad[12]; |   /* 0x0004 */ tint_array<int8_t, 12> tint_pad; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   /* 0x0000 */ strided_arr arr[4]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct LeftOver { | struct LeftOver { | ||||||
|   /* 0x0000 */ float4x4 worldViewProjection; |   /* 0x0000 */ float4x4 worldViewProjection; | ||||||
|   /* 0x0040 */ float time; |   /* 0x0040 */ float time; | ||||||
|   /* 0x0044 */ int8_t tint_pad_1[12]; |   /* 0x0044 */ tint_array<int8_t, 12> tint_pad_1; | ||||||
|   /* 0x0050 */ tint_array_wrapper test2; |   /* 0x0050 */ tint_array<float4x4, 2> test2; | ||||||
|   /* 0x00d0 */ tint_array_wrapper_1 test; |   /* 0x00d0 */ tint_array<strided_arr, 4> test; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void main_1(thread float3* const tint_symbol_5, const constant LeftOver* const tint_symbol_6, thread float4* const tint_symbol_7, thread float2* const tint_symbol_8, thread float2* const tint_symbol_9) { | void main_1(thread float3* const tint_symbol_5, const constant LeftOver* const tint_symbol_6, thread float4* const tint_symbol_7, thread float2* const tint_symbol_8, thread float2* const tint_symbol_9) { | ||||||
| @ -30,7 +35,7 @@ void main_1(thread float3* const tint_symbol_5, const constant LeftOver* const t | |||||||
|   float4 const x_21 = q; |   float4 const x_21 = q; | ||||||
|   p = float3(x_21[0], x_21[1], x_21[2]); |   p = float3(x_21[0], x_21[1], x_21[2]); | ||||||
|   float const x_27 = p[0]; |   float const x_27 = p[0]; | ||||||
|   float const x_41 = (*(tint_symbol_6)).test.arr[0].el; |   float const x_41 = (*(tint_symbol_6)).test[0].el; | ||||||
|   float const x_45 = (*(tint_symbol_5))[1]; |   float const x_45 = (*(tint_symbol_5))[1]; | ||||||
|   float const x_49 = (*(tint_symbol_6)).time; |   float const x_49 = (*(tint_symbol_6)).time; | ||||||
|   p[0] = (x_27 + sin(((x_41 * x_45) + x_49))); |   p[0] = (x_27 + sin(((x_41 * x_45) + x_49))); | ||||||
|  | |||||||
| @ -12,15 +12,27 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|   /* 0x0000 */ uint numTriangles; |   /* 0x0000 */ uint numTriangles; | ||||||
|   /* 0x0004 */ uint gridSize; |   /* 0x0004 */ uint gridSize; | ||||||
|   /* 0x0008 */ uint pad1; |   /* 0x0008 */ uint pad1; | ||||||
|   /* 0x000c */ uint pad2; |   /* 0x000c */ uint pad2; | ||||||
|   /* 0x0010 */ packed_float3 bbMin; |   /* 0x0010 */ packed_float3 bbMin; | ||||||
|   /* 0x001c */ int8_t tint_pad[4]; |   /* 0x001c */ tint_array<int8_t, 4> tint_pad; | ||||||
|   /* 0x0020 */ packed_float3 bbMax; |   /* 0x0020 */ packed_float3 bbMax; | ||||||
|   /* 0x002c */ int8_t tint_pad_1[4]; |   /* 0x002c */ tint_array<int8_t, 4> tint_pad_1; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Dbg { | struct Dbg { | ||||||
| @ -39,23 +51,23 @@ struct Dbg { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct F32s { | struct F32s { | ||||||
|   /* 0x0000 */ float values[1]; |   /* 0x0000 */ tint_array<float, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct U32s { | struct U32s { | ||||||
|   /* 0x0000 */ uint values[1]; |   /* 0x0000 */ tint_array<uint, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct I32s { | struct I32s { | ||||||
|   int values[1]; |   tint_array<int, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct AU32s { | struct AU32s { | ||||||
|   /* 0x0000 */ atomic_uint values[1]; |   /* 0x0000 */ tint_array<atomic_uint, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct AI32s { | struct AI32s { | ||||||
|   /* 0x0000 */ atomic_int values[1]; |   /* 0x0000 */ tint_array<atomic_int, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| float3 toVoxelPos(float3 position, const constant Uniforms* const tint_symbol_1) { | float3 toVoxelPos(float3 position, const constant Uniforms* const tint_symbol_1) { | ||||||
|  | |||||||
| @ -12,6 +12,18 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
|   return vec<T, M>(lhs) * rhs; |   return vec<T, M>(lhs) * rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct LightData { | struct LightData { | ||||||
|   /* 0x0000 */ float4 position; |   /* 0x0000 */ float4 position; | ||||||
|   /* 0x0010 */ packed_float3 color; |   /* 0x0010 */ packed_float3 color; | ||||||
| @ -19,24 +31,16 @@ struct LightData { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct LightsBuffer { | struct LightsBuffer { | ||||||
|   /* 0x0000 */ LightData lights[1]; |   /* 0x0000 */ tint_array<LightData, 1> lights; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ uint arr[64]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct TileLightIdData { | struct TileLightIdData { | ||||||
|   /* 0x0000 */ atomic_uint count; |   /* 0x0000 */ atomic_uint count; | ||||||
|   /* 0x0004 */ tint_array_wrapper lightId; |   /* 0x0004 */ tint_array<uint, 64> lightId; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   /* 0x0000 */ TileLightIdData arr[4]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Tiles { | struct Tiles { | ||||||
|   /* 0x0000 */ tint_array_wrapper_1 data; |   /* 0x0000 */ tint_array<TileLightIdData, 4> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Config { | struct Config { | ||||||
| @ -56,10 +60,6 @@ struct Uniforms { | |||||||
|   /* 0x00a0 */ float4 fullScreenSize; |   /* 0x00a0 */ float4 fullScreenSize; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   float4 arr[6]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void tint_symbol_inner(uint3 GlobalInvocationID, const constant Config* const tint_symbol_1, device LightsBuffer* const tint_symbol_2, const constant Uniforms* const tint_symbol_3, device Tiles* const tint_symbol_4) { | void tint_symbol_inner(uint3 GlobalInvocationID, const constant Config* const tint_symbol_1, device LightsBuffer* const tint_symbol_2, const constant Uniforms* const tint_symbol_3, device Tiles* const tint_symbol_4) { | ||||||
|   uint index = GlobalInvocationID[0]; |   uint index = GlobalInvocationID[0]; | ||||||
|   if ((index >= (*(tint_symbol_1)).numLights)) { |   if ((index >= (*(tint_symbol_1)).numLights)) { | ||||||
| @ -78,9 +78,9 @@ void tint_symbol_inner(uint3 GlobalInvocationID, const constant Config* const ti | |||||||
|   float lightRadius = (*(tint_symbol_2)).lights[index].radius; |   float lightRadius = (*(tint_symbol_2)).lights[index].radius; | ||||||
|   float4 boxMin = (lightPos - float4(float3(lightRadius), 0.0f)); |   float4 boxMin = (lightPos - float4(float3(lightRadius), 0.0f)); | ||||||
|   float4 boxMax = (lightPos + float4(float3(lightRadius), 0.0f)); |   float4 boxMax = (lightPos + float4(float3(lightRadius), 0.0f)); | ||||||
|   tint_array_wrapper_2 frustumPlanes = {}; |   tint_array<float4, 6> frustumPlanes = {}; | ||||||
|   frustumPlanes.arr[4] = float4(0.0f, 0.0f, -1.0f, viewNear); |   frustumPlanes[4] = float4(0.0f, 0.0f, -1.0f, viewNear); | ||||||
|   frustumPlanes.arr[5] = float4(0.0f, 0.0f, 1.0f, -(viewFar)); |   frustumPlanes[5] = float4(0.0f, 0.0f, 1.0f, -(viewFar)); | ||||||
|   int const TILE_SIZE = 16; |   int const TILE_SIZE = 16; | ||||||
|   int const TILE_COUNT_X = 2; |   int const TILE_COUNT_X = 2; | ||||||
|   int const TILE_COUNT_Y = 2; |   int const TILE_COUNT_Y = 2; | ||||||
| @ -91,41 +91,41 @@ void tint_symbol_inner(uint3 GlobalInvocationID, const constant Config* const ti | |||||||
|       float2 ceilCoord = (((2.0f * float2(as_type<int2>((as_type<uint2>(tilePixel0Idx) + as_type<uint2>(int2(16)))))) / float4((*(tint_symbol_3)).fullScreenSize).xy) - float2(1.0f)); |       float2 ceilCoord = (((2.0f * float2(as_type<int2>((as_type<uint2>(tilePixel0Idx) + as_type<uint2>(int2(16)))))) / float4((*(tint_symbol_3)).fullScreenSize).xy) - float2(1.0f)); | ||||||
|       float2 viewFloorCoord = float2((((-(viewNear) * floorCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * floorCoord[1]) - (M[2][1] * viewNear)) / M[1][1])); |       float2 viewFloorCoord = float2((((-(viewNear) * floorCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * floorCoord[1]) - (M[2][1] * viewNear)) / M[1][1])); | ||||||
|       float2 viewCeilCoord = float2((((-(viewNear) * ceilCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * ceilCoord[1]) - (M[2][1] * viewNear)) / M[1][1])); |       float2 viewCeilCoord = float2((((-(viewNear) * ceilCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * ceilCoord[1]) - (M[2][1] * viewNear)) / M[1][1])); | ||||||
|       frustumPlanes.arr[0] = float4(1.0f, 0.0f, (-(viewFloorCoord[0]) / viewNear), 0.0f); |       frustumPlanes[0] = float4(1.0f, 0.0f, (-(viewFloorCoord[0]) / viewNear), 0.0f); | ||||||
|       frustumPlanes.arr[1] = float4(-1.0f, 0.0f, (viewCeilCoord[0] / viewNear), 0.0f); |       frustumPlanes[1] = float4(-1.0f, 0.0f, (viewCeilCoord[0] / viewNear), 0.0f); | ||||||
|       frustumPlanes.arr[2] = float4(0.0f, 1.0f, (-(viewFloorCoord[1]) / viewNear), 0.0f); |       frustumPlanes[2] = float4(0.0f, 1.0f, (-(viewFloorCoord[1]) / viewNear), 0.0f); | ||||||
|       frustumPlanes.arr[3] = float4(0.0f, -1.0f, (viewCeilCoord[1] / viewNear), 0.0f); |       frustumPlanes[3] = float4(0.0f, -1.0f, (viewCeilCoord[1] / viewNear), 0.0f); | ||||||
|       float dp = 0.0f; |       float dp = 0.0f; | ||||||
|       for(uint i = 0u; (i < 6u); i = (i + 1u)) { |       for(uint i = 0u; (i < 6u); i = (i + 1u)) { | ||||||
|         float4 p = 0.0f; |         float4 p = 0.0f; | ||||||
|         if ((frustumPlanes.arr[i][0] > 0.0f)) { |         if ((frustumPlanes[i][0] > 0.0f)) { | ||||||
|           p[0] = boxMax[0]; |           p[0] = boxMax[0]; | ||||||
|         } else { |         } else { | ||||||
|           p[0] = boxMin[0]; |           p[0] = boxMin[0]; | ||||||
|         } |         } | ||||||
|         if ((frustumPlanes.arr[i][1] > 0.0f)) { |         if ((frustumPlanes[i][1] > 0.0f)) { | ||||||
|           p[1] = boxMax[1]; |           p[1] = boxMax[1]; | ||||||
|         } else { |         } else { | ||||||
|           p[1] = boxMin[1]; |           p[1] = boxMin[1]; | ||||||
|         } |         } | ||||||
|         if ((frustumPlanes.arr[i][2] > 0.0f)) { |         if ((frustumPlanes[i][2] > 0.0f)) { | ||||||
|           p[2] = boxMax[2]; |           p[2] = boxMax[2]; | ||||||
|         } else { |         } else { | ||||||
|           p[2] = boxMin[2]; |           p[2] = boxMin[2]; | ||||||
|         } |         } | ||||||
|         p[3] = 1.0f; |         p[3] = 1.0f; | ||||||
|         dp = (dp + fmin(0.0f, dot(p, frustumPlanes.arr[i]))); |         dp = (dp + fmin(0.0f, dot(p, frustumPlanes[i]))); | ||||||
|       } |       } | ||||||
|       if ((dp >= 0.0f)) { |       if ((dp >= 0.0f)) { | ||||||
|         uint tileId = uint(as_type<int>((as_type<uint>(x_1) + as_type<uint>(as_type<int>((as_type<uint>(y_1) * as_type<uint>(2))))))); |         uint tileId = uint(as_type<int>((as_type<uint>(x_1) + as_type<uint>(as_type<int>((as_type<uint>(y_1) * as_type<uint>(2))))))); | ||||||
|         if (((tileId < 0u) || (tileId >= (*(tint_symbol_1)).numTiles))) { |         if (((tileId < 0u) || (tileId >= (*(tint_symbol_1)).numTiles))) { | ||||||
|           continue; |           continue; | ||||||
|         } |         } | ||||||
|         uint offset = atomic_fetch_add_explicit(&((*(tint_symbol_4)).data.arr[tileId].count), 1u, memory_order_relaxed); |         uint offset = atomic_fetch_add_explicit(&((*(tint_symbol_4)).data[tileId].count), 1u, memory_order_relaxed); | ||||||
|         if ((offset >= (*(tint_symbol_1)).numTileLightSlot)) { |         if ((offset >= (*(tint_symbol_1)).numTileLightSlot)) { | ||||||
|           continue; |           continue; | ||||||
|         } |         } | ||||||
|         (*(tint_symbol_4)).data.arr[tileId].lightId.arr[offset] = GlobalInvocationID[0]; |         (*(tint_symbol_4)).data[tileId].lightId[offset] = GlobalInvocationID[0]; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -1,20 +1,29 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| int foo() { | int foo() { | ||||||
|   return 1; |   return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   float arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| fragment void tint_symbol() { | fragment void tint_symbol() { | ||||||
|   tint_array_wrapper arr = {.arr={}}; |   tint_array<float, 4> arr = tint_array<float, 4>{}; | ||||||
|   int const tint_symbol_1 = foo(); |   int const tint_symbol_1 = foo(); | ||||||
|   int const a_save = tint_symbol_1; |   int const a_save = tint_symbol_1; | ||||||
|   for(; ; ) { |   for(; ; ) { | ||||||
|     float const x = arr.arr[a_save]; |     float const x = arr[a_save]; | ||||||
|     break; |     break; | ||||||
|   } |   } | ||||||
|   return; |   return; | ||||||
|  | |||||||
| @ -1,11 +1,24 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_symbol_3 { | 
 | ||||||
|   /* 0x0000 */ int arr[1]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int foo(const device int (*const tint_symbol_1)[1]) { | struct tint_symbol_3 { | ||||||
|  |   /* 0x0000 */ tint_array<int, 1> arr; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int foo(const device tint_array<int, 1>* const tint_symbol_1) { | ||||||
|   return (*(tint_symbol_1))[0]; |   return (*(tint_symbol_1))[0]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,10 +1,23 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct UniformBuffer { | struct UniformBuffer { | ||||||
|   /* 0x0000 */ int8_t tint_pad[16]; |   /* 0x0000 */ tint_array<int8_t, 16> tint_pad; | ||||||
|   /* 0x0010 */ float unknownInput_S1_c0; |   /* 0x0010 */ float unknownInput_S1_c0; | ||||||
|   /* 0x0014 */ int8_t tint_pad_1[12]; |   /* 0x0014 */ tint_array<int8_t, 12> tint_pad_1; | ||||||
|   /* 0x0020 */ float4 ucolorRed_S1_c0; |   /* 0x0020 */ float4 ucolorRed_S1_c0; | ||||||
|   /* 0x0030 */ float4 ucolorGreen_S1_c0; |   /* 0x0030 */ float4 ucolorGreen_S1_c0; | ||||||
|   /* 0x0040 */ float3x3 umatrix_S1; |   /* 0x0040 */ float3x3 umatrix_S1; | ||||||
|  | |||||||
| @ -1,13 +1,22 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ uint arr[50]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Buf { | struct Buf { | ||||||
|   /* 0x0000 */ uint count; |   /* 0x0000 */ uint count; | ||||||
|   /* 0x0004 */ tint_array_wrapper data; |   /* 0x0004 */ tint_array<uint, 50> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(device Buf* tint_symbol_1 [[buffer(0)]]) { | kernel void tint_symbol(device Buf* tint_symbol_1 [[buffer(0)]]) { | ||||||
| @ -19,14 +28,14 @@ kernel void tint_symbol(device Buf* tint_symbol_1 [[buffer(0)]]) { | |||||||
|     uint const p_save = i; |     uint const p_save = i; | ||||||
|     if (((i % 2u) == 0u)) { |     if (((i % 2u) == 0u)) { | ||||||
|       { |       { | ||||||
|         (*(tint_symbol_1)).data.arr[p_save] = ((*(tint_symbol_1)).data.arr[p_save] * 2u); |         (*(tint_symbol_1)).data[p_save] = ((*(tint_symbol_1)).data[p_save] * 2u); | ||||||
|         i = (i + 1u); |         i = (i + 1u); | ||||||
|       } |       } | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|     (*(tint_symbol_1)).data.arr[p_save] = 0u; |     (*(tint_symbol_1)).data[p_save] = 0u; | ||||||
|     { |     { | ||||||
|       (*(tint_symbol_1)).data.arr[p_save] = ((*(tint_symbol_1)).data.arr[p_save] * 2u); |       (*(tint_symbol_1)).data[p_save] = ((*(tint_symbol_1)).data[p_save] * 2u); | ||||||
|       i = (i + 1u); |       i = (i + 1u); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Light { | struct Light { | ||||||
|   float3 position; |   float3 position; | ||||||
|   float3 colour; |   float3 colour; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Lights { | struct Lights { | ||||||
|   Light light[1]; |   tint_array<Light, 1> light; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct vertexUniformBuffer1 { | struct vertexUniformBuffer1 { | ||||||
|   /* 0x0000 */ float2x2 transform1; |   /* 0x0000 */ float2x2 transform1; | ||||||
| }; | }; | ||||||
| @ -13,18 +26,14 @@ struct tint_symbol_1 { | |||||||
|   float4 value [[position]]; |   float4 value [[position]]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   float2 arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| float4 tint_symbol_inner(uint gl_VertexIndex, const constant vertexUniformBuffer1* const tint_symbol_3, const constant vertexUniformBuffer2* const tint_symbol_4) { | float4 tint_symbol_inner(uint gl_VertexIndex, const constant vertexUniformBuffer1* const tint_symbol_3, const constant vertexUniformBuffer2* const tint_symbol_4) { | ||||||
|   tint_array_wrapper indexable = {}; |   tint_array<float2, 3> indexable = {}; | ||||||
|   float2x2 const x_23 = (*(tint_symbol_3)).transform1; |   float2x2 const x_23 = (*(tint_symbol_3)).transform1; | ||||||
|   float2x2 const x_28 = (*(tint_symbol_4)).transform2; |   float2x2 const x_28 = (*(tint_symbol_4)).transform2; | ||||||
|   uint const x_46 = gl_VertexIndex; |   uint const x_46 = gl_VertexIndex; | ||||||
|   tint_array_wrapper const tint_symbol_2 = {.arr={float2(-1.0f, 1.0f), float2(1.0f), float2(-1.0f)}}; |   tint_array<float2, 3> const tint_symbol_2 = tint_array<float2, 3>{float2(-1.0f, 1.0f), float2(1.0f), float2(-1.0f)}; | ||||||
|   indexable = tint_symbol_2; |   indexable = tint_symbol_2; | ||||||
|   float2 const x_51 = indexable.arr[x_46]; |   float2 const x_51 = indexable[x_46]; | ||||||
|   float2 const x_52 = (float2x2((x_23[0u] + x_28[0u]), (x_23[1u] + x_28[1u])) * x_51); |   float2 const x_52 = (float2x2((x_23[0u] + x_28[0u]), (x_23[1u] + x_28[1u])) * x_51); | ||||||
|   return float4(x_52[0], x_52[1], 0.0f, 1.0f); |   return float4(x_52[0], x_52[1], 0.0f, 1.0f); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|   /* 0x0000 */ uint dstTextureFlipY; |   /* 0x0000 */ uint dstTextureFlipY; | ||||||
|   /* 0x0004 */ uint isFloat16; |   /* 0x0004 */ uint isFloat16; | ||||||
| @ -9,7 +22,7 @@ struct Uniforms { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct OutputBuf { | struct OutputBuf { | ||||||
|   /* 0x0000 */ uint result[1]; |   /* 0x0000 */ tint_array<uint, 1> result; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| uint ConvertToFp16FloatValue(float fp32) { | uint ConvertToFp16FloatValue(float fp32) { | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|   /* 0x0000 */ uint2 aShape; |   /* 0x0000 */ uint2 aShape; | ||||||
|   /* 0x0008 */ uint2 bShape; |   /* 0x0008 */ uint2 bShape; | ||||||
| @ -8,7 +21,7 @@ struct Uniforms { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Matrix { | struct Matrix { | ||||||
|   /* 0x0000 */ uint numbers[1]; |   /* 0x0000 */ tint_array<uint, 1> numbers; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void tint_symbol_inner(uint3 global_id, const constant Uniforms* const tint_symbol_1, const device Matrix* const tint_symbol_2, const device Matrix* const tint_symbol_3, device Matrix* const tint_symbol_4) { | void tint_symbol_inner(uint3 global_id, const constant Uniforms* const tint_symbol_1, const device Matrix* const tint_symbol_2, const device Matrix* const tint_symbol_3, device Matrix* const tint_symbol_4) { | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Constants { | struct Constants { | ||||||
|   int level; |   int level; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Result { | struct Result { | ||||||
|   /* 0x0000 */ float values[1]; |   /* 0x0000 */ tint_array<float, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void tint_symbol_inner(uint3 GlobalInvocationID, texture2d_array<float, access::sample> tint_symbol_1, device Result* const tint_symbol_2) { | void tint_symbol_inner(uint3 GlobalInvocationID, texture2d_array<float, access::sample> tint_symbol_1, device Result* const tint_symbol_2) { | ||||||
|  | |||||||
| @ -1,13 +1,22 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   int arr[2]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void foo() { | void foo() { | ||||||
|   tint_array_wrapper tint_symbol = {}; |   tint_array<int, 2> tint_symbol = {}; | ||||||
|   tint_array_wrapper implict = {}; |   tint_array<int, 2> implict = {}; | ||||||
|   implict = tint_symbol; |   implict = tint_symbol; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Output { | struct Output { | ||||||
|   float4 Position; |   float4 Position; | ||||||
|   float4 color; |   float4 color; | ||||||
| @ -11,21 +24,13 @@ struct tint_symbol_1 { | |||||||
|   float4 Position [[position]]; |   float4 Position [[position]]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   float2 arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   float4 arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| Output tint_symbol_inner(uint VertexIndex, uint InstanceIndex) { | Output tint_symbol_inner(uint VertexIndex, uint InstanceIndex) { | ||||||
|   tint_array_wrapper const zv = {.arr={float2(0.200000003f), float2(0.300000012f), float2(-0.100000001f), float2(1.100000024f)}}; |   tint_array<float2, 4> const zv = tint_array<float2, 4>{float2(0.200000003f), float2(0.300000012f), float2(-0.100000001f), float2(1.100000024f)}; | ||||||
|   float const z = zv.arr[InstanceIndex][0]; |   float const z = zv[InstanceIndex][0]; | ||||||
|   Output output = {}; |   Output output = {}; | ||||||
|   output.Position = float4(0.5f, 0.5f, z, 1.0f); |   output.Position = float4(0.5f, 0.5f, z, 1.0f); | ||||||
|   tint_array_wrapper_1 const colors = {.arr={float4(1.0f, 0.0f, 0.0f, 1.0f), float4(0.0f, 1.0f, 0.0f, 1.0f), float4(0.0f, 0.0f, 1.0f, 1.0f), float4(1.0f)}}; |   tint_array<float4, 4> const colors = tint_array<float4, 4>{float4(1.0f, 0.0f, 0.0f, 1.0f), float4(0.0f, 1.0f, 0.0f, 1.0f), float4(0.0f, 0.0f, 1.0f, 1.0f), float4(1.0f)}; | ||||||
|   output.color = colors.arr[InstanceIndex]; |   output.color = colors[InstanceIndex]; | ||||||
|   return output; |   return output; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,8 +1,21 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Result { | struct Result { | ||||||
|   /* 0x0000 */ float values[1]; |   /* 0x0000 */ tint_array<float, 1> values; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| constant uint width = 128u; | constant uint width = 128u; | ||||||
|  | |||||||
| @ -1,15 +1,24 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| struct tint_array_wrapper { | 
 | ||||||
|   /* 0x0000 */ int arr[6]; | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct sspp962805860buildInformationS { | struct sspp962805860buildInformationS { | ||||||
|   /* 0x0000 */ float4 footprint; |   /* 0x0000 */ float4 footprint; | ||||||
|   /* 0x0010 */ float4 offset; |   /* 0x0010 */ float4 offset; | ||||||
|   /* 0x0020 */ int essence; |   /* 0x0020 */ int essence; | ||||||
|   /* 0x0024 */ tint_array_wrapper orientation; |   /* 0x0024 */ tint_array<int, 6> orientation; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct x_B4_BuildInformation { | struct x_B4_BuildInformation { | ||||||
| @ -17,14 +26,14 @@ struct x_B4_BuildInformation { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void main_1(const device x_B4_BuildInformation* const tint_symbol_1) { | void main_1(const device x_B4_BuildInformation* const tint_symbol_1) { | ||||||
|   tint_array_wrapper orientation = {}; |   tint_array<int, 6> orientation = {}; | ||||||
|   tint_array_wrapper const x_23 = (*(tint_symbol_1)).passthru.orientation; |   tint_array<int, 6> const x_23 = (*(tint_symbol_1)).passthru.orientation; | ||||||
|   orientation.arr[0] = x_23.arr[0u]; |   orientation[0] = x_23[0u]; | ||||||
|   orientation.arr[1] = x_23.arr[1u]; |   orientation[1] = x_23[1u]; | ||||||
|   orientation.arr[2] = x_23.arr[2u]; |   orientation[2] = x_23[2u]; | ||||||
|   orientation.arr[3] = x_23.arr[3u]; |   orientation[3] = x_23[3u]; | ||||||
|   orientation.arr[4] = x_23.arr[4u]; |   orientation[4] = x_23[4u]; | ||||||
|   orientation.arr[5] = x_23.arr[5u]; |   orientation[5] = x_23[5u]; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|   /* 0x0000 */ uint dstTextureFlipY; |   /* 0x0000 */ uint dstTextureFlipY; | ||||||
|   /* 0x0004 */ uint channelCount; |   /* 0x0004 */ uint channelCount; | ||||||
| @ -10,7 +23,7 @@ struct Uniforms { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct OutputBuf { | struct OutputBuf { | ||||||
|   /* 0x0000 */ uint result[1]; |   /* 0x0000 */ tint_array<uint, 1> result; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| bool aboutEqual(float value, float expect) { | bool aboutEqual(float value, float expect) { | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|   /* 0x0000 */ uint dimAOuter; |   /* 0x0000 */ uint dimAOuter; | ||||||
|   /* 0x0004 */ uint dimInner; |   /* 0x0004 */ uint dimInner; | ||||||
| @ -8,7 +21,7 @@ struct Uniforms { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Matrix { | struct Matrix { | ||||||
|   /* 0x0000 */ float numbers[1]; |   /* 0x0000 */ tint_array<float, 1> numbers; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| float mm_readA(uint row, uint col, const constant Uniforms* const tint_symbol_3, const device Matrix* const tint_symbol_4) { | float mm_readA(uint row, uint col, const constant Uniforms* const tint_symbol_3, const device Matrix* const tint_symbol_4) { | ||||||
| @ -44,28 +57,12 @@ constant uint TileBOuter = 64u; | |||||||
| 
 | 
 | ||||||
| constant uint TileInner = 64u; | constant uint TileInner = 64u; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_1 { | void tint_symbol_inner(uint3 local_id, uint3 global_id, uint local_invocation_index, threadgroup tint_array<tint_array<float, 64>, 64>* const tint_symbol_9, threadgroup tint_array<tint_array<float, 64>, 64>* const tint_symbol_10, const constant Uniforms* const tint_symbol_11, const device Matrix* const tint_symbol_12, const device Matrix* const tint_symbol_13, device Matrix* const tint_symbol_14) { | ||||||
|   float arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   tint_array_wrapper_1 arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   float arr[16]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_3 { |  | ||||||
|   float arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void tint_symbol_inner(uint3 local_id, uint3 global_id, uint local_invocation_index, threadgroup tint_array_wrapper* const tint_symbol_9, threadgroup tint_array_wrapper* const tint_symbol_10, const constant Uniforms* const tint_symbol_11, const device Matrix* const tint_symbol_12, const device Matrix* const tint_symbol_13, device Matrix* const tint_symbol_14) { |  | ||||||
|   for(uint idx = local_invocation_index; (idx < 4096u); idx = (idx + 256u)) { |   for(uint idx = local_invocation_index; (idx < 4096u); idx = (idx + 256u)) { | ||||||
|     uint const i = (idx / 64u); |     uint const i = (idx / 64u); | ||||||
|     uint const i_1 = (idx % 64u); |     uint const i_1 = (idx % 64u); | ||||||
|     (*(tint_symbol_9)).arr[i].arr[i_1] = 0.0f; |     (*(tint_symbol_9))[i][i_1] = 0.0f; | ||||||
|     (*(tint_symbol_10)).arr[i].arr[i_1] = 0.0f; |     (*(tint_symbol_10))[i][i_1] = 0.0f; | ||||||
|   } |   } | ||||||
|   threadgroup_barrier(mem_flags::mem_threadgroup); |   threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
|   uint const tileRow = (local_id[1] * 4u); |   uint const tileRow = (local_id[1] * 4u); | ||||||
| @ -73,11 +70,11 @@ void tint_symbol_inner(uint3 local_id, uint3 global_id, uint local_invocation_in | |||||||
|   uint const globalRow = (global_id[1] * 4u); |   uint const globalRow = (global_id[1] * 4u); | ||||||
|   uint const globalCol = (global_id[0] * 4u); |   uint const globalCol = (global_id[0] * 4u); | ||||||
|   uint const numTiles = ((((*(tint_symbol_11)).dimInner - 1u) / 64u) + 1u); |   uint const numTiles = ((((*(tint_symbol_11)).dimInner - 1u) / 64u) + 1u); | ||||||
|   tint_array_wrapper_2 acc = {}; |   tint_array<float, 16> acc = {}; | ||||||
|   float ACached = 0.0f; |   float ACached = 0.0f; | ||||||
|   tint_array_wrapper_3 BCached = {}; |   tint_array<float, 4> BCached = {}; | ||||||
|   for(uint index = 0u; (index < (4u * 4u)); index = (index + 1u)) { |   for(uint index = 0u; (index < (4u * 4u)); index = (index + 1u)) { | ||||||
|     acc.arr[index] = 0.0f; |     acc[index] = 0.0f; | ||||||
|   } |   } | ||||||
|   uint const ColPerThreadA = (64u / 16u); |   uint const ColPerThreadA = (64u / 16u); | ||||||
|   uint const tileColA = (local_id[0] * ColPerThreadA); |   uint const tileColA = (local_id[0] * ColPerThreadA); | ||||||
| @ -89,7 +86,7 @@ void tint_symbol_inner(uint3 local_id, uint3 global_id, uint local_invocation_in | |||||||
|         uint const inputRow = (tileRow + innerRow); |         uint const inputRow = (tileRow + innerRow); | ||||||
|         uint const inputCol = (tileColA + innerCol); |         uint const inputCol = (tileColA + innerCol); | ||||||
|         float const tint_symbol_1 = mm_readA((globalRow + innerRow), ((t * 64u) + inputCol), tint_symbol_11, tint_symbol_12); |         float const tint_symbol_1 = mm_readA((globalRow + innerRow), ((t * 64u) + inputCol), tint_symbol_11, tint_symbol_12); | ||||||
|         (*(tint_symbol_9)).arr[inputRow].arr[inputCol] = tint_symbol_1; |         (*(tint_symbol_9))[inputRow][inputCol] = tint_symbol_1; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     for(uint innerRow = 0u; (innerRow < RowPerThreadB); innerRow = (innerRow + 1u)) { |     for(uint innerRow = 0u; (innerRow < RowPerThreadB); innerRow = (innerRow + 1u)) { | ||||||
| @ -97,19 +94,19 @@ void tint_symbol_inner(uint3 local_id, uint3 global_id, uint local_invocation_in | |||||||
|         uint const inputRow = (tileRowB + innerRow); |         uint const inputRow = (tileRowB + innerRow); | ||||||
|         uint const inputCol = (tileCol + innerCol); |         uint const inputCol = (tileCol + innerCol); | ||||||
|         float const tint_symbol_2 = mm_readB(((t * 64u) + inputRow), (globalCol + innerCol), tint_symbol_11, tint_symbol_13); |         float const tint_symbol_2 = mm_readB(((t * 64u) + inputRow), (globalCol + innerCol), tint_symbol_11, tint_symbol_13); | ||||||
|         (*(tint_symbol_10)).arr[innerCol].arr[inputCol] = tint_symbol_2; |         (*(tint_symbol_10))[innerCol][inputCol] = tint_symbol_2; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     threadgroup_barrier(mem_flags::mem_threadgroup); |     threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
|     for(uint k = 0u; (k < 64u); k = (k + 1u)) { |     for(uint k = 0u; (k < 64u); k = (k + 1u)) { | ||||||
|       for(uint inner = 0u; (inner < 4u); inner = (inner + 1u)) { |       for(uint inner = 0u; (inner < 4u); inner = (inner + 1u)) { | ||||||
|         BCached.arr[inner] = (*(tint_symbol_10)).arr[k].arr[(tileCol + inner)]; |         BCached[inner] = (*(tint_symbol_10))[k][(tileCol + inner)]; | ||||||
|       } |       } | ||||||
|       for(uint innerRow = 0u; (innerRow < 4u); innerRow = (innerRow + 1u)) { |       for(uint innerRow = 0u; (innerRow < 4u); innerRow = (innerRow + 1u)) { | ||||||
|         ACached = (*(tint_symbol_9)).arr[(tileRow + innerRow)].arr[k]; |         ACached = (*(tint_symbol_9))[(tileRow + innerRow)][k]; | ||||||
|         for(uint innerCol = 0u; (innerCol < 4u); innerCol = (innerCol + 1u)) { |         for(uint innerCol = 0u; (innerCol < 4u); innerCol = (innerCol + 1u)) { | ||||||
|           uint const index = ((innerRow * 4u) + innerCol); |           uint const index = ((innerRow * 4u) + innerCol); | ||||||
|           acc.arr[index] = (acc.arr[index] + (ACached * BCached.arr[innerCol])); |           acc[index] = (acc[index] + (ACached * BCached[innerCol])); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @ -118,14 +115,14 @@ void tint_symbol_inner(uint3 local_id, uint3 global_id, uint local_invocation_in | |||||||
|   for(uint innerRow = 0u; (innerRow < 4u); innerRow = (innerRow + 1u)) { |   for(uint innerRow = 0u; (innerRow < 4u); innerRow = (innerRow + 1u)) { | ||||||
|     for(uint innerCol = 0u; (innerCol < 4u); innerCol = (innerCol + 1u)) { |     for(uint innerCol = 0u; (innerCol < 4u); innerCol = (innerCol + 1u)) { | ||||||
|       uint const index = ((innerRow * 4u) + innerCol); |       uint const index = ((innerRow * 4u) + innerCol); | ||||||
|       mm_write((globalRow + innerRow), (globalCol + innerCol), acc.arr[index], tint_symbol_11, tint_symbol_14); |       mm_write((globalRow + innerRow), (globalCol + innerCol), acc[index], tint_symbol_11, tint_symbol_14); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant Uniforms* tint_symbol_17 [[buffer(0)]], const device Matrix* tint_symbol_18 [[buffer(2)]], const device Matrix* tint_symbol_19 [[buffer(3)]], device Matrix* tint_symbol_20 [[buffer(1)]], uint3 local_id [[thread_position_in_threadgroup]], uint3 global_id [[thread_position_in_grid]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | kernel void tint_symbol(const constant Uniforms* tint_symbol_17 [[buffer(0)]], const device Matrix* tint_symbol_18 [[buffer(2)]], const device Matrix* tint_symbol_19 [[buffer(3)]], device Matrix* tint_symbol_20 [[buffer(1)]], uint3 local_id [[thread_position_in_threadgroup]], uint3 global_id [[thread_position_in_grid]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | ||||||
|   threadgroup tint_array_wrapper tint_symbol_15; |   threadgroup tint_array<tint_array<float, 64>, 64> tint_symbol_15; | ||||||
|   threadgroup tint_array_wrapper tint_symbol_16; |   threadgroup tint_array<tint_array<float, 64>, 64> tint_symbol_16; | ||||||
|   tint_symbol_inner(local_id, global_id, local_invocation_index, &(tint_symbol_15), &(tint_symbol_16), tint_symbol_17, tint_symbol_18, tint_symbol_19, tint_symbol_20); |   tint_symbol_inner(local_id, global_id, local_invocation_index, &(tint_symbol_15), &(tint_symbol_16), tint_symbol_17, tint_symbol_18, tint_symbol_19, tint_symbol_20); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Mat4x4_ { | struct Mat4x4_ { | ||||||
|   /* 0x0000 */ float4 mx; |   /* 0x0000 */ float4 mx; | ||||||
|   /* 0x0010 */ float4 my; |   /* 0x0010 */ float4 my; | ||||||
| @ -23,21 +36,13 @@ struct ub_SceneParams { | |||||||
|   /* 0x0000 */ Mat4x4_ u_Projection; |   /* 0x0000 */ Mat4x4_ u_Projection; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ Mat4x2_ arr[1]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct ub_MaterialParams { | struct ub_MaterialParams { | ||||||
|   /* 0x0000 */ tint_array_wrapper u_TexMtx; |   /* 0x0000 */ tint_array<Mat4x2_, 1> u_TexMtx; | ||||||
|   /* 0x0020 */ float4 u_Misc0_; |   /* 0x0020 */ float4 u_Misc0_; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   /* 0x0000 */ Mat4x3_ arr[32]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct ub_PacketParams { | struct ub_PacketParams { | ||||||
|   /* 0x0000 */ tint_array_wrapper_1 u_PosMtx; |   /* 0x0000 */ tint_array<Mat4x3_, 32> u_PosMtx; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct VertexOutput { | struct VertexOutput { | ||||||
| @ -222,7 +227,7 @@ void main1(thread float* const tint_symbol_5, const constant ub_PacketParams* co | |||||||
|   Mat4x3_ t_PosMtx = {}; |   Mat4x3_ t_PosMtx = {}; | ||||||
|   float2 t_TexSpaceCoord = 0.0f; |   float2 t_TexSpaceCoord = 0.0f; | ||||||
|   float const x_e15 = *(tint_symbol_5); |   float const x_e15 = *(tint_symbol_5); | ||||||
|   Mat4x3_ const x_e18 = (*(tint_symbol_6)).u_PosMtx.arr[int(x_e15)]; |   Mat4x3_ const x_e18 = (*(tint_symbol_6)).u_PosMtx[int(x_e15)]; | ||||||
|   t_PosMtx = x_e18; |   t_PosMtx = x_e18; | ||||||
|   Mat4x3_ const x_e23 = t_PosMtx; |   Mat4x3_ const x_e23 = t_PosMtx; | ||||||
|   Mat4x4_ const x_e24 = x_Mat4x4_1(x_e23); |   Mat4x4_ const x_e24 = x_Mat4x4_1(x_e23); | ||||||
| @ -247,7 +252,7 @@ void main1(thread float* const tint_symbol_5, const constant ub_PacketParams* co | |||||||
|   if ((x_e52[0] == 2.0f)) { |   if ((x_e52[0] == 2.0f)) { | ||||||
|     { |     { | ||||||
|       float3 const x_e59 = *(tint_symbol_13); |       float3 const x_e59 = *(tint_symbol_13); | ||||||
|       Mat4x2_ const x_e64 = (*(tint_symbol_12)).u_TexMtx.arr[0]; |       Mat4x2_ const x_e64 = (*(tint_symbol_12)).u_TexMtx[0]; | ||||||
|       float3 const x_e65 = *(tint_symbol_13); |       float3 const x_e65 = *(tint_symbol_13); | ||||||
|       float2 const x_e68 = Mul2(x_e64, float4(x_e65, 1.0f)); |       float2 const x_e68 = Mul2(x_e64, float4(x_e65, 1.0f)); | ||||||
|       *(tint_symbol_14) = float2(x_e68).xy; |       *(tint_symbol_14) = float2(x_e68).xy; | ||||||
| @ -256,7 +261,7 @@ void main1(thread float* const tint_symbol_5, const constant ub_PacketParams* co | |||||||
|   } else { |   } else { | ||||||
|     { |     { | ||||||
|       float2 const x_e73 = *(tint_symbol_15); |       float2 const x_e73 = *(tint_symbol_15); | ||||||
|       Mat4x2_ const x_e79 = (*(tint_symbol_12)).u_TexMtx.arr[0]; |       Mat4x2_ const x_e79 = (*(tint_symbol_12)).u_TexMtx[0]; | ||||||
|       float2 const x_e80 = *(tint_symbol_15); |       float2 const x_e80 = *(tint_symbol_15); | ||||||
|       float2 const x_e84 = Mul2(x_e79, float4(x_e80, 1.0f, 1.0f)); |       float2 const x_e84 = Mul2(x_e79, float4(x_e80, 1.0f, 1.0f)); | ||||||
|       *(tint_symbol_14) = float2(x_e84).xy; |       *(tint_symbol_14) = float2(x_e84).xy; | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Params { | struct Params { | ||||||
|   /* 0x0000 */ uint filterDim; |   /* 0x0000 */ uint filterDim; | ||||||
|   /* 0x0004 */ uint blockDim; |   /* 0x0004 */ uint blockDim; | ||||||
| @ -10,19 +23,11 @@ struct Flip { | |||||||
|   /* 0x0000 */ uint value; |   /* 0x0000 */ uint value; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_1 { | void tint_symbol_inner(uint3 WorkGroupID, uint3 LocalInvocationID, uint local_invocation_index, threadgroup tint_array<tint_array<float3, 256>, 4>* const tint_symbol_1, const constant Params* const tint_symbol_2, texture2d<float, access::sample> tint_symbol_3, const constant Flip* const tint_symbol_4, sampler tint_symbol_5, texture2d<float, access::write> tint_symbol_6) { | ||||||
|   float3 arr[256]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   tint_array_wrapper_1 arr[4]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void tint_symbol_inner(uint3 WorkGroupID, uint3 LocalInvocationID, uint local_invocation_index, threadgroup tint_array_wrapper* const tint_symbol_1, const constant Params* const tint_symbol_2, texture2d<float, access::sample> tint_symbol_3, const constant Flip* const tint_symbol_4, sampler tint_symbol_5, texture2d<float, access::write> tint_symbol_6) { |  | ||||||
|   for(uint idx = local_invocation_index; (idx < 1024u); idx = (idx + 64u)) { |   for(uint idx = local_invocation_index; (idx < 1024u); idx = (idx + 64u)) { | ||||||
|     uint const i_1 = (idx / 256u); |     uint const i_1 = (idx / 256u); | ||||||
|     uint const i_2 = (idx % 256u); |     uint const i_2 = (idx % 256u); | ||||||
|     (*(tint_symbol_1)).arr[i_1].arr[i_2] = float3(0.0f); |     (*(tint_symbol_1))[i_1][i_2] = float3(0.0f); | ||||||
|   } |   } | ||||||
|   threadgroup_barrier(mem_flags::mem_threadgroup); |   threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
|   uint const filterOffset = (((*(tint_symbol_2)).filterDim - 1u) / 2u); |   uint const filterOffset = (((*(tint_symbol_2)).filterDim - 1u) / 2u); | ||||||
| @ -34,7 +39,7 @@ void tint_symbol_inner(uint3 WorkGroupID, uint3 LocalInvocationID, uint local_in | |||||||
|       if (((*(tint_symbol_4)).value != 0u)) { |       if (((*(tint_symbol_4)).value != 0u)) { | ||||||
|         loadIndex = int2(loadIndex).yx; |         loadIndex = int2(loadIndex).yx; | ||||||
|       } |       } | ||||||
|       (*(tint_symbol_1)).arr[r].arr[((4u * LocalInvocationID[0]) + c)] = float4(tint_symbol_3.sample(tint_symbol_5, ((float2(loadIndex) + float2(0.25f)) / float2(dims)), level(0.0f))).rgb; |       (*(tint_symbol_1))[r][((4u * LocalInvocationID[0]) + c)] = float4(tint_symbol_3.sample(tint_symbol_5, ((float2(loadIndex) + float2(0.25f)) / float2(dims)), level(0.0f))).rgb; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   threadgroup_barrier(mem_flags::mem_threadgroup); |   threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
| @ -49,7 +54,7 @@ void tint_symbol_inner(uint3 WorkGroupID, uint3 LocalInvocationID, uint local_in | |||||||
|         float3 acc = float3(0.0f); |         float3 acc = float3(0.0f); | ||||||
|         for(uint f = 0u; (f < (*(tint_symbol_2)).filterDim); f = (f + 1u)) { |         for(uint f = 0u; (f < (*(tint_symbol_2)).filterDim); f = (f + 1u)) { | ||||||
|           uint i = ((center + f) - filterOffset); |           uint i = ((center + f) - filterOffset); | ||||||
|           acc = (acc + ((1.0f / float((*(tint_symbol_2)).filterDim)) * (*(tint_symbol_1)).arr[r].arr[i])); |           acc = (acc + ((1.0f / float((*(tint_symbol_2)).filterDim)) * (*(tint_symbol_1))[r][i])); | ||||||
|         } |         } | ||||||
|         tint_symbol_6.write(float4(acc, 1.0f), uint2(writeIndex)); |         tint_symbol_6.write(float4(acc, 1.0f), uint2(writeIndex)); | ||||||
|       } |       } | ||||||
| @ -58,7 +63,7 @@ void tint_symbol_inner(uint3 WorkGroupID, uint3 LocalInvocationID, uint local_in | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant Params* tint_symbol_8 [[buffer(0)]], texture2d<float, access::sample> tint_symbol_9 [[texture(0)]], const constant Flip* tint_symbol_10 [[buffer(1)]], sampler tint_symbol_11 [[sampler(0)]], texture2d<float, access::write> tint_symbol_12 [[texture(1)]], uint3 WorkGroupID [[threadgroup_position_in_grid]], uint3 LocalInvocationID [[thread_position_in_threadgroup]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | kernel void tint_symbol(const constant Params* tint_symbol_8 [[buffer(0)]], texture2d<float, access::sample> tint_symbol_9 [[texture(0)]], const constant Flip* tint_symbol_10 [[buffer(1)]], sampler tint_symbol_11 [[sampler(0)]], texture2d<float, access::write> tint_symbol_12 [[texture(1)]], uint3 WorkGroupID [[threadgroup_position_in_grid]], uint3 LocalInvocationID [[thread_position_in_threadgroup]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | ||||||
|   threadgroup tint_array_wrapper tint_symbol_7; |   threadgroup tint_array<tint_array<float3, 256>, 4> tint_symbol_7; | ||||||
|   tint_symbol_inner(WorkGroupID, LocalInvocationID, local_invocation_index, &(tint_symbol_7), tint_symbol_8, tint_symbol_9, tint_symbol_10, tint_symbol_11, tint_symbol_12); |   tint_symbol_inner(WorkGroupID, LocalInvocationID, local_invocation_index, &(tint_symbol_7), tint_symbol_8, tint_symbol_9, tint_symbol_10, tint_symbol_11, tint_symbol_12); | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,44 +4,41 @@ note: reading from module-scope private variable 'dimInner_1' may result in a no | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|   /* 0x0000 */ float tint_symbol; |   /* 0x0000 */ float tint_symbol; | ||||||
|   /* 0x0004 */ int8_t tint_pad[12]; |   /* 0x0004 */ tint_array<int8_t, 12> tint_pad; | ||||||
|   /* 0x0010 */ packed_int3 aShape; |   /* 0x0010 */ packed_int3 aShape; | ||||||
|   /* 0x001c */ int8_t tint_pad_1[4]; |   /* 0x001c */ tint_array<int8_t, 4> tint_pad_1; | ||||||
|   /* 0x0020 */ packed_int3 bShape; |   /* 0x0020 */ packed_int3 bShape; | ||||||
|   /* 0x002c */ int8_t tint_pad_2[4]; |   /* 0x002c */ tint_array<int8_t, 4> tint_pad_2; | ||||||
|   /* 0x0030 */ packed_int3 outShape; |   /* 0x0030 */ packed_int3 outShape; | ||||||
|   /* 0x003c */ int8_t tint_pad_3[4]; |   /* 0x003c */ tint_array<int8_t, 4> tint_pad_3; | ||||||
|   /* 0x0040 */ int2 outShapeStrides; |   /* 0x0040 */ int2 outShapeStrides; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ssbOut { | struct ssbOut { | ||||||
|   /* 0x0000 */ float result[1]; |   /* 0x0000 */ tint_array<float, 1> result; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ssbA { | struct ssbA { | ||||||
|   /* 0x0000 */ float A[1]; |   /* 0x0000 */ tint_array<float, 1> A; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ssbB { | struct ssbB { | ||||||
|   /* 0x0000 */ float B[1]; |   /* 0x0000 */ tint_array<float, 1> B; | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_1 { |  | ||||||
|   float arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper { |  | ||||||
|   tint_array_wrapper_1 arr[64]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_3 { |  | ||||||
|   float arr[1]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct tint_array_wrapper_2 { |  | ||||||
|   tint_array_wrapper_3 arr[64]; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| bool coordsInBounds_vi2_vi2_(thread int2* const coord, thread int2* const shape) { | bool coordsInBounds_vi2_vi2_(thread int2* const coord, thread int2* const shape) { | ||||||
| @ -175,11 +172,7 @@ void mm_write_i1_i1_f1_(thread int* const row_2, thread int* const col_2, thread | |||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper_4 { | void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner, thread int* const dimBOuter, thread uint3* const tint_symbol_19, thread uint3* const tint_symbol_20, const constant Uniforms* const tint_symbol_21, thread int* const tint_symbol_22, thread int* const tint_symbol_23, thread int* const tint_symbol_24, const device ssbA* const tint_symbol_25, threadgroup tint_array<tint_array<float, 64>, 64>* const tint_symbol_26, thread int* const tint_symbol_27, const device ssbB* const tint_symbol_28, threadgroup tint_array<tint_array<float, 1>, 64>* const tint_symbol_29, device ssbOut* const tint_symbol_30) { | ||||||
|   tint_array_wrapper_3 arr[1]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner, thread int* const dimBOuter, thread uint3* const tint_symbol_19, thread uint3* const tint_symbol_20, const constant Uniforms* const tint_symbol_21, thread int* const tint_symbol_22, thread int* const tint_symbol_23, thread int* const tint_symbol_24, const device ssbA* const tint_symbol_25, threadgroup tint_array_wrapper* const tint_symbol_26, thread int* const tint_symbol_27, const device ssbB* const tint_symbol_28, threadgroup tint_array_wrapper_2* const tint_symbol_29, device ssbOut* const tint_symbol_30) { |  | ||||||
|   int tileRow = 0; |   int tileRow = 0; | ||||||
|   int tileCol = 0; |   int tileCol = 0; | ||||||
|   int globalRow = 0; |   int globalRow = 0; | ||||||
| @ -187,7 +180,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|   int numTiles = 0; |   int numTiles = 0; | ||||||
|   int innerRow = 0; |   int innerRow = 0; | ||||||
|   int innerCol = 0; |   int innerCol = 0; | ||||||
|   tint_array_wrapper_4 acc = {}; |   tint_array<tint_array<float, 1>, 1> acc = {}; | ||||||
|   int tileColA = 0; |   int tileColA = 0; | ||||||
|   int tileRowB = 0; |   int tileRowB = 0; | ||||||
|   int t = 0; |   int t = 0; | ||||||
| @ -205,7 +198,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|   int param_6 = 0; |   int param_6 = 0; | ||||||
|   int k = 0; |   int k = 0; | ||||||
|   int inner = 0; |   int inner = 0; | ||||||
|   tint_array_wrapper_3 BCached = {}; |   tint_array<float, 1> BCached = {}; | ||||||
|   int innerRow_3 = 0; |   int innerRow_3 = 0; | ||||||
|   float ACached = 0.0f; |   float ACached = 0.0f; | ||||||
|   int innerCol_3 = 0; |   int innerCol_3 = 0; | ||||||
| @ -240,7 +233,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|       } |       } | ||||||
|       int const x_177 = innerRow; |       int const x_177 = innerRow; | ||||||
|       int const x_178 = innerCol; |       int const x_178 = innerCol; | ||||||
|       acc.arr[x_177].arr[x_178] = 0.0f; |       acc[x_177][x_178] = 0.0f; | ||||||
|       { |       { | ||||||
|         int const x_181 = innerCol; |         int const x_181 = innerCol; | ||||||
|         innerCol = as_type<int>((as_type<uint>(x_181) + as_type<uint>(1))); |         innerCol = as_type<int>((as_type<uint>(x_181) + as_type<uint>(1))); | ||||||
| @ -292,7 +285,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|         param_3 = as_type<int>((as_type<uint>(x_235) + as_type<uint>(x_236))); |         param_3 = as_type<int>((as_type<uint>(x_235) + as_type<uint>(x_236))); | ||||||
|         param_4 = as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(x_238) * as_type<uint>(64)))) + as_type<uint>(x_240))); |         param_4 = as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(x_238) * as_type<uint>(64)))) + as_type<uint>(x_240))); | ||||||
|         float const x_244 = mm_readA_i1_i1_(&(param_3), &(param_4), tint_symbol_21, tint_symbol_22, tint_symbol_23, tint_symbol_24, tint_symbol_25); |         float const x_244 = mm_readA_i1_i1_(&(param_3), &(param_4), tint_symbol_21, tint_symbol_22, tint_symbol_23, tint_symbol_24, tint_symbol_25); | ||||||
|         (*(tint_symbol_26)).arr[x_233].arr[x_234] = x_244; |         (*(tint_symbol_26))[x_233][x_234] = x_244; | ||||||
|         { |         { | ||||||
|           int const x_247 = innerCol_1; |           int const x_247 = innerCol_1; | ||||||
|           innerCol_1 = as_type<int>((as_type<uint>(x_247) + as_type<uint>(1))); |           innerCol_1 = as_type<int>((as_type<uint>(x_247) + as_type<uint>(1))); | ||||||
| @ -332,7 +325,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|         param_5 = as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(x_280) * as_type<uint>(64)))) + as_type<uint>(x_282))); |         param_5 = as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(x_280) * as_type<uint>(64)))) + as_type<uint>(x_282))); | ||||||
|         param_6 = as_type<int>((as_type<uint>(x_284) + as_type<uint>(x_285))); |         param_6 = as_type<int>((as_type<uint>(x_284) + as_type<uint>(x_285))); | ||||||
|         float const x_289 = mm_readB_i1_i1_(&(param_5), &(param_6), tint_symbol_21, tint_symbol_23, tint_symbol_27, tint_symbol_24, tint_symbol_28); |         float const x_289 = mm_readB_i1_i1_(&(param_5), &(param_6), tint_symbol_21, tint_symbol_23, tint_symbol_27, tint_symbol_24, tint_symbol_28); | ||||||
|         (*(tint_symbol_29)).arr[x_278].arr[x_279] = x_289; |         (*(tint_symbol_29))[x_278][x_279] = x_289; | ||||||
|         { |         { | ||||||
|           int const x_291 = innerCol_2; |           int const x_291 = innerCol_2; | ||||||
|           innerCol_2 = as_type<int>((as_type<uint>(x_291) + as_type<uint>(1))); |           innerCol_2 = as_type<int>((as_type<uint>(x_291) + as_type<uint>(1))); | ||||||
| @ -362,8 +355,8 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|         int const x_315 = k; |         int const x_315 = k; | ||||||
|         int const x_316 = tileCol; |         int const x_316 = tileCol; | ||||||
|         int const x_317 = inner; |         int const x_317 = inner; | ||||||
|         float const x_320 = (*(tint_symbol_29)).arr[x_315].arr[as_type<int>((as_type<uint>(x_316) + as_type<uint>(x_317)))]; |         float const x_320 = (*(tint_symbol_29))[x_315][as_type<int>((as_type<uint>(x_316) + as_type<uint>(x_317)))]; | ||||||
|         BCached.arr[x_314] = x_320; |         BCached[x_314] = x_320; | ||||||
|         { |         { | ||||||
|           int const x_322 = inner; |           int const x_322 = inner; | ||||||
|           inner = as_type<int>((as_type<uint>(x_322) + as_type<uint>(1))); |           inner = as_type<int>((as_type<uint>(x_322) + as_type<uint>(1))); | ||||||
| @ -379,7 +372,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|         int const x_333 = tileRow; |         int const x_333 = tileRow; | ||||||
|         int const x_334 = innerRow_3; |         int const x_334 = innerRow_3; | ||||||
|         int const x_336 = k; |         int const x_336 = k; | ||||||
|         float const x_338 = (*(tint_symbol_26)).arr[as_type<int>((as_type<uint>(x_333) + as_type<uint>(x_334)))].arr[x_336]; |         float const x_338 = (*(tint_symbol_26))[as_type<int>((as_type<uint>(x_333) + as_type<uint>(x_334)))][x_336]; | ||||||
|         ACached = x_338; |         ACached = x_338; | ||||||
|         innerCol_3 = 0; |         innerCol_3 = 0; | ||||||
|         while (true) { |         while (true) { | ||||||
| @ -392,9 +385,9 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|           int const x_348 = innerCol_3; |           int const x_348 = innerCol_3; | ||||||
|           float const x_349 = ACached; |           float const x_349 = ACached; | ||||||
|           int const x_350 = innerCol_3; |           int const x_350 = innerCol_3; | ||||||
|           float const x_352 = BCached.arr[x_350]; |           float const x_352 = BCached[x_350]; | ||||||
|           float const x_355 = acc.arr[x_347].arr[x_348]; |           float const x_355 = acc[x_347][x_348]; | ||||||
|           acc.arr[x_347].arr[x_348] = (x_355 + (x_349 * x_352)); |           acc[x_347][x_348] = (x_355 + (x_349 * x_352)); | ||||||
|           { |           { | ||||||
|             int const x_358 = innerCol_3; |             int const x_358 = innerCol_3; | ||||||
|             innerCol_3 = as_type<int>((as_type<uint>(x_358) + as_type<uint>(1))); |             innerCol_3 = as_type<int>((as_type<uint>(x_358) + as_type<uint>(1))); | ||||||
| @ -454,7 +447,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|         int const x_404 = innerCol_4; |         int const x_404 = innerCol_4; | ||||||
|         param_7 = as_type<int>((as_type<uint>(x_397) + as_type<uint>(x_398))); |         param_7 = as_type<int>((as_type<uint>(x_397) + as_type<uint>(x_398))); | ||||||
|         param_8 = as_type<int>((as_type<uint>(x_400) + as_type<uint>(x_401))); |         param_8 = as_type<int>((as_type<uint>(x_400) + as_type<uint>(x_401))); | ||||||
|         float const x_409 = acc.arr[x_403].arr[x_404]; |         float const x_409 = acc[x_403][x_404]; | ||||||
|         param_9 = x_409; |         param_9 = x_409; | ||||||
|         mm_write_i1_i1_f1_(&(param_7), &(param_8), &(param_9), tint_symbol_24, tint_symbol_21, tint_symbol_30); |         mm_write_i1_i1_f1_(&(param_7), &(param_8), &(param_9), tint_symbol_24, tint_symbol_21, tint_symbol_30); | ||||||
|       } |       } | ||||||
| @ -471,7 +464,7 @@ void mm_matMul_i1_i1_i1_(thread int* const dimAOuter, thread int* const dimInner | |||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void main_1(const constant Uniforms* const tint_symbol_31, thread int* const tint_symbol_32, thread int* const tint_symbol_33, thread int* const tint_symbol_34, thread uint3* const tint_symbol_35, thread int* const tint_symbol_36, thread uint3* const tint_symbol_37, const device ssbA* const tint_symbol_38, threadgroup tint_array_wrapper* const tint_symbol_39, const device ssbB* const tint_symbol_40, threadgroup tint_array_wrapper_2* const tint_symbol_41, device ssbOut* const tint_symbol_42) { | void main_1(const constant Uniforms* const tint_symbol_31, thread int* const tint_symbol_32, thread int* const tint_symbol_33, thread int* const tint_symbol_34, thread uint3* const tint_symbol_35, thread int* const tint_symbol_36, thread uint3* const tint_symbol_37, const device ssbA* const tint_symbol_38, threadgroup tint_array<tint_array<float, 64>, 64>* const tint_symbol_39, const device ssbB* const tint_symbol_40, threadgroup tint_array<tint_array<float, 1>, 64>* const tint_symbol_41, device ssbOut* const tint_symbol_42) { | ||||||
|   int param_18 = 0; |   int param_18 = 0; | ||||||
|   int param_19 = 0; |   int param_19 = 0; | ||||||
|   int param_20 = 0; |   int param_20 = 0; | ||||||
| @ -493,16 +486,16 @@ void main_1(const constant Uniforms* const tint_symbol_31, thread int* const tin | |||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void tint_symbol_1_inner(uint3 gl_LocalInvocationID_param, uint3 gl_GlobalInvocationID_param, uint local_invocation_index, threadgroup tint_array_wrapper_2* const tint_symbol_43, threadgroup tint_array_wrapper* const tint_symbol_44, thread uint3* const tint_symbol_45, thread uint3* const tint_symbol_46, const constant Uniforms* const tint_symbol_47, thread int* const tint_symbol_48, thread int* const tint_symbol_49, thread int* const tint_symbol_50, thread int* const tint_symbol_51, const device ssbA* const tint_symbol_52, const device ssbB* const tint_symbol_53, device ssbOut* const tint_symbol_54) { | void tint_symbol_1_inner(uint3 gl_LocalInvocationID_param, uint3 gl_GlobalInvocationID_param, uint local_invocation_index, threadgroup tint_array<tint_array<float, 1>, 64>* const tint_symbol_43, threadgroup tint_array<tint_array<float, 64>, 64>* const tint_symbol_44, thread uint3* const tint_symbol_45, thread uint3* const tint_symbol_46, const constant Uniforms* const tint_symbol_47, thread int* const tint_symbol_48, thread int* const tint_symbol_49, thread int* const tint_symbol_50, thread int* const tint_symbol_51, const device ssbA* const tint_symbol_52, const device ssbB* const tint_symbol_53, device ssbOut* const tint_symbol_54) { | ||||||
|   { |   { | ||||||
|     uint const i_1 = local_invocation_index; |     uint const i_1 = local_invocation_index; | ||||||
|     uint const i_2 = (local_invocation_index % 1u); |     uint const i_2 = (local_invocation_index % 1u); | ||||||
|     (*(tint_symbol_43)).arr[i_1].arr[i_2] = 0.0f; |     (*(tint_symbol_43))[i_1][i_2] = 0.0f; | ||||||
|   } |   } | ||||||
|   for(uint idx = local_invocation_index; (idx < 4096u); idx = (idx + 64u)) { |   for(uint idx = local_invocation_index; (idx < 4096u); idx = (idx + 64u)) { | ||||||
|     uint const i = (idx / 64u); |     uint const i = (idx / 64u); | ||||||
|     uint const i_1 = (idx % 64u); |     uint const i_1 = (idx % 64u); | ||||||
|     (*(tint_symbol_44)).arr[i].arr[i_1] = 0.0f; |     (*(tint_symbol_44))[i][i_1] = 0.0f; | ||||||
|   } |   } | ||||||
|   threadgroup_barrier(mem_flags::mem_threadgroup); |   threadgroup_barrier(mem_flags::mem_threadgroup); | ||||||
|   *(tint_symbol_45) = gl_LocalInvocationID_param; |   *(tint_symbol_45) = gl_LocalInvocationID_param; | ||||||
| @ -511,8 +504,8 @@ void tint_symbol_1_inner(uint3 gl_LocalInvocationID_param, uint3 gl_GlobalInvoca | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol_1(const constant Uniforms* tint_symbol_59 [[buffer(0)]], const device ssbA* tint_symbol_64 [[buffer(2)]], const device ssbB* tint_symbol_65 [[buffer(3)]], device ssbOut* tint_symbol_66 [[buffer(1)]], uint3 gl_LocalInvocationID_param [[thread_position_in_threadgroup]], uint3 gl_GlobalInvocationID_param [[thread_position_in_grid]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | kernel void tint_symbol_1(const constant Uniforms* tint_symbol_59 [[buffer(0)]], const device ssbA* tint_symbol_64 [[buffer(2)]], const device ssbB* tint_symbol_65 [[buffer(3)]], device ssbOut* tint_symbol_66 [[buffer(1)]], uint3 gl_LocalInvocationID_param [[thread_position_in_threadgroup]], uint3 gl_GlobalInvocationID_param [[thread_position_in_grid]], uint local_invocation_index [[thread_index_in_threadgroup]]) { | ||||||
|   threadgroup tint_array_wrapper_2 tint_symbol_55; |   threadgroup tint_array<tint_array<float, 1>, 64> tint_symbol_55; | ||||||
|   threadgroup tint_array_wrapper tint_symbol_56; |   threadgroup tint_array<tint_array<float, 64>, 64> tint_symbol_56; | ||||||
|   thread uint3 tint_symbol_57 = 0u; |   thread uint3 tint_symbol_57 = 0u; | ||||||
|   thread uint3 tint_symbol_58 = 0u; |   thread uint3 tint_symbol_58 = 0u; | ||||||
|   thread int tint_symbol_60 = 0; |   thread int tint_symbol_60 = 0; | ||||||
|  | |||||||
| @ -14,6 +14,18 @@ bug/tint/948.wgsl:137:27 note: reading from module-scope private variable 'mt' m | |||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| 
 | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| template<typename T, int N, int M> | template<typename T, int N, int M> | ||||||
| inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | ||||||
|   return lhs * vec<T, N>(rhs); |   return lhs * vec<T, N>(rhs); | ||||||
| @ -27,7 +39,7 @@ inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) { | |||||||
| struct LeftOver { | struct LeftOver { | ||||||
|   /* 0x0000 */ float time; |   /* 0x0000 */ float time; | ||||||
|   /* 0x0004 */ uint padding; |   /* 0x0004 */ uint padding; | ||||||
|   /* 0x0008 */ int8_t tint_pad[8]; |   /* 0x0008 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0010 */ float4x4 worldViewProjection; |   /* 0x0010 */ float4x4 worldViewProjection; | ||||||
|   /* 0x0050 */ float2 outputSize; |   /* 0x0050 */ float2 outputSize; | ||||||
|   /* 0x0058 */ float2 stageSize; |   /* 0x0058 */ float2 stageSize; | ||||||
| @ -35,7 +47,7 @@ struct LeftOver { | |||||||
|   /* 0x0068 */ float stageScale; |   /* 0x0068 */ float stageScale; | ||||||
|   /* 0x006c */ float spriteCount; |   /* 0x006c */ float spriteCount; | ||||||
|   /* 0x0070 */ packed_float3 colorMul; |   /* 0x0070 */ packed_float3 colorMul; | ||||||
|   /* 0x007c */ int8_t tint_pad_1[4]; |   /* 0x007c */ tint_array<int8_t, 4> tint_pad_1; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| float4x4 getFrameData_f1_(thread float* const frameID, const constant LeftOver* const tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7) { | float4x4 getFrameData_f1_(thread float* const frameID, const constant LeftOver* const tint_symbol_5, texture2d<float, access::sample> tint_symbol_6, sampler tint_symbol_7) { | ||||||
|  | |||||||
| @ -14,6 +14,18 @@ bug/tint/949.wgsl:308:27 note: reading from module-scope private variable 'v_out | |||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
| 
 | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| template<typename T, int N, int M> | template<typename T, int N, int M> | ||||||
| inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) { | ||||||
|   return lhs * vec<T, N>(rhs); |   return lhs * vec<T, N>(rhs); | ||||||
| @ -34,7 +46,7 @@ struct LeftOver { | |||||||
|   /* 0x0040 */ float4x4 u_ViewProjection; |   /* 0x0040 */ float4x4 u_ViewProjection; | ||||||
|   /* 0x0080 */ float u_bumpStrength; |   /* 0x0080 */ float u_bumpStrength; | ||||||
|   /* 0x0084 */ uint padding; |   /* 0x0084 */ uint padding; | ||||||
|   /* 0x0088 */ int8_t tint_pad[8]; |   /* 0x0088 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0090 */ packed_float3 u_cameraPosition; |   /* 0x0090 */ packed_float3 u_cameraPosition; | ||||||
|   /* 0x009c */ float u_parallaxScale; |   /* 0x009c */ float u_parallaxScale; | ||||||
|   /* 0x00a0 */ float textureInfoName; |   /* 0x00a0 */ float textureInfoName; | ||||||
| @ -50,7 +62,7 @@ struct Light0 { | |||||||
|   /* 0x003c */ uint padding_2; |   /* 0x003c */ uint padding_2; | ||||||
|   /* 0x0040 */ float4 shadowsInfo; |   /* 0x0040 */ float4 shadowsInfo; | ||||||
|   /* 0x0050 */ float2 depthValues; |   /* 0x0050 */ float2 depthValues; | ||||||
|   /* 0x0058 */ int8_t tint_pad_1[8]; |   /* 0x0058 */ tint_array<int8_t, 8> tint_pad_1; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| float3x3 cotangent_frame_vf3_vf3_vf2_vf2_(thread float3* const normal_1, thread float3* const p, thread float2* const uv, thread float2* const tangentSpaceParams) { | float3x3 cotangent_frame_vf3_vf3_vf2_vf2_(thread float3* const normal_1, thread float3* const p, thread float2* const uv, thread float2* const tangentSpaceParams) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct ssbOut { | struct ssbOut { | ||||||
|   /* 0x0000 */ float result[1]; |   /* 0x0000 */ tint_array<float, 1> result; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ssbA { | struct ssbA { | ||||||
|   /* 0x0000 */ float A[1]; |   /* 0x0000 */ tint_array<float, 1> A; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|  | |||||||
| @ -1,16 +1,29 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct ResultMatrix { | struct ResultMatrix { | ||||||
|   /* 0x0000 */ float numbers[1]; |   /* 0x0000 */ tint_array<float, 1> numbers; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct FirstMatrix { | struct FirstMatrix { | ||||||
|   float numbers[1]; |   tint_array<float, 1> numbers; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SecondMatrix { | struct SecondMatrix { | ||||||
|   float numbers[1]; |   tint_array<float, 1> numbers; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct Uniforms { | struct Uniforms { | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Constants { | struct Constants { | ||||||
|   /* 0x0000 */ uint zero; |   /* 0x0000 */ uint zero; | ||||||
| }; | }; | ||||||
| @ -9,16 +22,12 @@ struct Result { | |||||||
|   /* 0x0000 */ uint value; |   /* 0x0000 */ uint value; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   /* 0x0000 */ atomic_int arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TestData { | struct TestData { | ||||||
|   /* 0x0000 */ tint_array_wrapper data; |   /* 0x0000 */ tint_array<atomic_int, 3> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int runTest(device TestData* const tint_symbol_3, const constant Constants* const tint_symbol_4) { | int runTest(device TestData* const tint_symbol_3, const constant Constants* const tint_symbol_4) { | ||||||
|   return atomic_load_explicit(&((*(tint_symbol_3)).data.arr[(0u + uint((*(tint_symbol_4)).zero))]), memory_order_relaxed); |   return atomic_load_explicit(&((*(tint_symbol_3)).data[(0u + uint((*(tint_symbol_4)).zero))]), memory_order_relaxed); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(device TestData* tint_symbol_5 [[buffer(2)]], const constant Constants* tint_symbol_6 [[buffer(0)]], device Result* tint_symbol_7 [[buffer(1)]]) { | kernel void tint_symbol(device TestData* tint_symbol_5 [[buffer(2)]], const constant Constants* tint_symbol_6 [[buffer(0)]], device Result* tint_symbol_7 [[buffer(1)]]) { | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct Constants { | struct Constants { | ||||||
|   /* 0x0000 */ uint zero; |   /* 0x0000 */ uint zero; | ||||||
| }; | }; | ||||||
| @ -9,17 +22,13 @@ struct Result { | |||||||
|   uint value; |   uint value; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct tint_array_wrapper { |  | ||||||
|   uint arr[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct S { | struct S { | ||||||
|   tint_array_wrapper data; |   tint_array<uint, 3> data; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant Constants* tint_symbol_2 [[buffer(0)]]) { | kernel void tint_symbol(const constant Constants* tint_symbol_2 [[buffer(0)]]) { | ||||||
|   thread S tint_symbol_1 = {}; |   thread S tint_symbol_1 = {}; | ||||||
|   tint_symbol_1.data.arr[(*(tint_symbol_2)).zero] = 0u; |   tint_symbol_1.data[(*(tint_symbol_2)).zero] = 0u; | ||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   int a[1]; |   tint_array<int, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,8 +1,21 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   int a[1]; |   tint_array<int, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   int a[1]; |   tint_array<int, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,8 +1,21 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   int a[1]; |   tint_array<int, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct S { | struct S { | ||||||
|   int a[1]; |   tint_array<int, 1> a; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,8 +1,21 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,8 +1,21 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | kernel void tint_symbol(const constant tint_symbol_1* tint_symbol_3 [[buffer(30)]]) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RO { | struct SB_RO { | ||||||
|   int arg_0[1]; |   tint_array<int, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_1588cd(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_1588cd(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RW { | struct SB_RW { | ||||||
|   int arg_0[1]; |   tint_array<int, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_61b1c7(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_61b1c7(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RO { | struct SB_RO { | ||||||
|   float arg_0[1]; |   tint_array<float, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_a0f5ca(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_a0f5ca(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RW { | struct SB_RW { | ||||||
|   float arg_0[1]; |   tint_array<float, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_cdd123(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_cdd123(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RO { | struct SB_RO { | ||||||
|   uint arg_0[1]; |   tint_array<uint, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_cfca0a(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_cfca0a(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RW { | struct SB_RW { | ||||||
|   uint arg_0[1]; |   tint_array<uint, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_eb510f(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_eb510f(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct GammaTransferParams { | struct GammaTransferParams { | ||||||
|   /* 0x0000 */ float G; |   /* 0x0000 */ float G; | ||||||
|   /* 0x0004 */ float A; |   /* 0x0004 */ float A; | ||||||
| @ -15,7 +28,7 @@ struct GammaTransferParams { | |||||||
| struct ExternalTextureParams { | struct ExternalTextureParams { | ||||||
|   /* 0x0000 */ uint numPlanes; |   /* 0x0000 */ uint numPlanes; | ||||||
|   /* 0x0004 */ uint doYuvToRgbConversionOnly; |   /* 0x0004 */ uint doYuvToRgbConversionOnly; | ||||||
|   /* 0x0008 */ int8_t tint_pad[8]; |   /* 0x0008 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix; |   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix; | ||||||
|   /* 0x0040 */ GammaTransferParams gammaDecodeParams; |   /* 0x0040 */ GammaTransferParams gammaDecodeParams; | ||||||
|   /* 0x0060 */ GammaTransferParams gammaEncodeParams; |   /* 0x0060 */ GammaTransferParams gammaEncodeParams; | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct GammaTransferParams { | struct GammaTransferParams { | ||||||
|   /* 0x0000 */ float G; |   /* 0x0000 */ float G; | ||||||
|   /* 0x0004 */ float A; |   /* 0x0004 */ float A; | ||||||
| @ -15,7 +28,7 @@ struct GammaTransferParams { | |||||||
| struct ExternalTextureParams { | struct ExternalTextureParams { | ||||||
|   /* 0x0000 */ uint numPlanes; |   /* 0x0000 */ uint numPlanes; | ||||||
|   /* 0x0004 */ uint doYuvToRgbConversionOnly; |   /* 0x0004 */ uint doYuvToRgbConversionOnly; | ||||||
|   /* 0x0008 */ int8_t tint_pad[8]; |   /* 0x0008 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix; |   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix; | ||||||
|   /* 0x0040 */ GammaTransferParams gammaDecodeParams; |   /* 0x0040 */ GammaTransferParams gammaDecodeParams; | ||||||
|   /* 0x0060 */ GammaTransferParams gammaEncodeParams; |   /* 0x0060 */ GammaTransferParams gammaEncodeParams; | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RO { | struct SB_RO { | ||||||
|   int arg_0[1]; |   tint_array<int, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_1588cd(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_1588cd(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RW { | struct SB_RW { | ||||||
|   int arg_0[1]; |   tint_array<int, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_61b1c7(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_61b1c7(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RO { | struct SB_RO { | ||||||
|   float arg_0[1]; |   tint_array<float, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_a0f5ca(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_a0f5ca(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RW { | struct SB_RW { | ||||||
|   float arg_0[1]; |   tint_array<float, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_cdd123(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_cdd123(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RO { | struct SB_RO { | ||||||
|   uint arg_0[1]; |   tint_array<uint, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_cfca0a(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_cfca0a(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,12 +1,25 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct tint_symbol_1 { | struct tint_symbol_1 { | ||||||
|   /* 0x0000 */ uint4 buffer_size[1]; |   /* 0x0000 */ tint_array<uint4, 1> buffer_size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SB_RW { | struct SB_RW { | ||||||
|   uint arg_0[1]; |   tint_array<uint, 1> arg_0; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void arrayLength_eb510f(const constant tint_symbol_1* const tint_symbol_3) { | void arrayLength_eb510f(const constant tint_symbol_1* const tint_symbol_3) { | ||||||
|  | |||||||
| @ -1,6 +1,19 @@ | |||||||
| #include <metal_stdlib> | #include <metal_stdlib> | ||||||
| 
 | 
 | ||||||
| using namespace metal; | using namespace metal; | ||||||
|  | 
 | ||||||
|  | template<typename T, size_t N> | ||||||
|  | struct tint_array { | ||||||
|  |     const constant T& operator[](size_t i) const constant { return elements[i]; } | ||||||
|  |     device T& operator[](size_t i) device { return elements[i]; } | ||||||
|  |     const device T& operator[](size_t i) const device { return elements[i]; } | ||||||
|  |     thread T& operator[](size_t i) thread { return elements[i]; } | ||||||
|  |     const thread T& operator[](size_t i) const thread { return elements[i]; } | ||||||
|  |     threadgroup T& operator[](size_t i) threadgroup { return elements[i]; } | ||||||
|  |     const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; } | ||||||
|  |     T elements[N]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct GammaTransferParams { | struct GammaTransferParams { | ||||||
|   /* 0x0000 */ float G; |   /* 0x0000 */ float G; | ||||||
|   /* 0x0004 */ float A; |   /* 0x0004 */ float A; | ||||||
| @ -15,7 +28,7 @@ struct GammaTransferParams { | |||||||
| struct ExternalTextureParams { | struct ExternalTextureParams { | ||||||
|   /* 0x0000 */ uint numPlanes; |   /* 0x0000 */ uint numPlanes; | ||||||
|   /* 0x0004 */ uint doYuvToRgbConversionOnly; |   /* 0x0004 */ uint doYuvToRgbConversionOnly; | ||||||
|   /* 0x0008 */ int8_t tint_pad[8]; |   /* 0x0008 */ tint_array<int8_t, 8> tint_pad; | ||||||
|   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix; |   /* 0x0010 */ float3x4 yuvToRgbConversionMatrix; | ||||||
|   /* 0x0040 */ GammaTransferParams gammaDecodeParams; |   /* 0x0040 */ GammaTransferParams gammaDecodeParams; | ||||||
|   /* 0x0060 */ GammaTransferParams gammaEncodeParams; |   /* 0x0060 */ GammaTransferParams gammaEncodeParams; | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user