From d47eb3a965d861f7c5289dcb482f3ee96bcef78a Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Wed, 16 Jun 2021 09:50:11 +0000 Subject: [PATCH] writer/hlsl: Generate padding for UBO padded structs Combined with the new PadArrayElements transform, arrays with strides are now correctly emitted. Fixed: tint:182 Fixed: tint:895 Change-Id: I26a1be94dee6e4c9d9747c8317a932fc1fb3c810 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54640 Kokoro: Kokoro Reviewed-by: James Price --- src/writer/hlsl/generator_impl.cc | 218 +++++++- src/writer/hlsl/generator_impl.h | 11 + .../hlsl/generator_impl_function_test.cc | 6 +- src/writer/hlsl/generator_impl_type_test.cc | 465 ++++++++++++++++-- src/writer/msl/generator_impl.cc | 1 + .../assign_to_function_var.wgsl.expected.hlsl | 27 +- .../assign_to_private_var.wgsl.expected.hlsl | 25 +- .../assign_to_storage_var.wgsl.expected.hlsl | 31 +- ...assign_to_workgroup_var.wgsl.expected.hlsl | 25 +- test/bug/tint/744.wgsl.expected.hlsl | 6 +- test/bug/tint/757.wgsl.expected.hlsl | 2 +- test/bug/tint/870.spvasm.expected.hlsl | 2 +- .../load/local/ptr_uniform.wgsl.expected.hlsl | 2 +- test/samples/compute_boids.wgsl.expected.hlsl | 14 +- test/samples/cube.wgsl.expected.hlsl | 2 +- ...d_struct_storage_buffer.wgsl.expected.hlsl | 20 +- 16 files changed, 756 insertions(+), 101 deletions(-) diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index eded04894f..8cde6f9b69 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -14,6 +14,8 @@ #include "src/writer/hlsl/generator_impl.h" +#include +#include #include #include @@ -1343,7 +1345,11 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& pre, type->is_scalar_vector() && expr->values().size() == 1 && TypeOf(expr->values()[0])->is_scalar(); - if (brackets) { + auto it = structure_builders_.find(As(type)); + if (it != structure_builders_.end()) { + out << it->second << "("; + brackets = false; + } else if (brackets) { out << "{"; } else { if (!EmitType(out, type, ast::StorageClass::kNone, ast::Access::kReadWrite, @@ -1904,7 +1910,13 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) { } } } else if (auto* str = type->As()) { - out << "{"; + auto it = structure_builders_.find(str); + if (it != structure_builders_.end()) { + out << it->second << "("; + } else { + out << "{"; + } + bool first = true; for (auto* member : str->Members()) { if (!first) { @@ -1915,7 +1927,8 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) { return false; } } - out << "}"; + + out << (it != structure_builders_.end() ? ")" : "}"); } else if (auto* arr = type->As()) { out << "{"; auto* elem = arr->ElemType(); @@ -2244,23 +2257,75 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) { return true; } - auto name = builder_.Symbols().NameFor(str->Declaration()->name()); - out << "struct " << name << " {" << std::endl; + bool is_host_shareable = str->IsHostShareable(); + uint32_t hlsl_offset = 0; + + // Emits a `/* 0xnnnn */` byte offset comment for a struct member. + auto add_byte_offset_comment = [&](uint32_t offset) { + std::ios_base::fmtflags saved_flag_state(out.flags()); + out << "/* 0x" << std::hex << std::setfill('0') << std::setw(4) << offset + << " */ "; + out.flags(saved_flag_state); + }; + + uint32_t pad_count = 0; + auto add_padding = [&](uint32_t size) { + if (size & 3) { + TINT_ICE(builder_.Diagnostics()) + << "attempting to pad field with " << size + << " bytes, but we require a multiple of 4 bytes"; + return false; + } + std::string name; + do { + name = "tint_pad_" + std::to_string(pad_count++); + } while (str->FindMember(builder_.Symbols().Get(name))); + + out << "int " << name << "[" << (size / 4) << "];" << std::endl; + return true; + }; + + auto struct_name = builder_.Symbols().NameFor(str->Declaration()->name()); + out << "struct " << struct_name << " {" << std::endl; increment_indent(); for (auto* mem : str->Members()) { make_indent(out); - // TODO(dsinclair): Handle [[offset]] annotation on structs - // https://bugs.chromium.org/p/tint/issues/detail?id=184 - auto mem_name = builder_.Symbols().NameFor(mem->Declaration()->symbol()); - if (!EmitType(out, mem->Type(), ast::StorageClass::kNone, - ast::Access::kReadWrite, mem_name)) { + auto name = builder_.Symbols().NameFor(mem->Declaration()->symbol()); + auto wgsl_offset = mem->Offset(); + + if (is_host_shareable) { + if (wgsl_offset < hlsl_offset) { + // Unimplementable layout + TINT_ICE(diagnostics_) + << "Structure member WGSL offset (" << wgsl_offset + << ") is behind HLSL offset (" << hlsl_offset << ")"; + return false; + } + + // Generate padding if required + if (auto padding = wgsl_offset - hlsl_offset) { + add_byte_offset_comment(hlsl_offset); + if (!add_padding(padding)) { + return false; + } + hlsl_offset += padding; + make_indent(out); + } + + add_byte_offset_comment(hlsl_offset); + } + + auto* ty = mem->Type(); + + if (!EmitType(out, ty, ast::StorageClass::kNone, ast::Access::kReadWrite, + name)) { return false; } // Array member name will be output with the type - if (!mem->Type()->Is()) { - out << " " << mem_name; + if (!ty->Is()) { + out << " " << name; } for (auto* deco : mem->Declaration()->decorations()) { @@ -2295,12 +2360,84 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) { } out << ";" << std::endl; + + if (is_host_shareable) { + // Calculate new HLSL offset + auto size_align = HlslPackedTypeSizeAndAlign(ty); + if (hlsl_offset % size_align.align) { + TINT_ICE(diagnostics_) + << "Misaligned HLSL structure member " + << ty->FriendlyName(builder_.Symbols()) << " " << name; + return false; + } + hlsl_offset += size_align.size; + } } + + if (is_host_shareable && str->Size() != hlsl_offset) { + make_indent(out); + add_byte_offset_comment(hlsl_offset); + if (!add_padding(str->Size() - hlsl_offset)) { + return false; + } + } + decrement_indent(); make_indent(out); out << "};" << std::endl; + // If the structure has padding members, create a helper function for building + // the structure. + if (pad_count) { + auto builder_name = generate_name("make_" + struct_name); + + out << std::endl; + out << struct_name << " " << builder_name << "("; + uint32_t idx = 0; + for (auto* mem : str->Members()) { + if (idx > 0) { + out << ","; + make_indent(out << std::endl); + out << std::string(struct_name.length() + builder_name.length() + 2, + ' '); + } + auto name = "param_" + std::to_string(idx++); + auto* ty = mem->Type(); + if (!EmitType(out, ty, ast::StorageClass::kNone, ast::Access::kReadWrite, + name)) { + return false; + } + + // Array member name will be output with the type + if (!ty->Is()) { + out << " " << name; + } + } + out << ") {"; + increment_indent(); + make_indent(out << std::endl); + + out << struct_name << " output;"; + make_indent(out << std::endl); + idx = 0; + for (auto* mem : str->Members()) { + out << "output." + << builder_.Symbols().NameFor(mem->Declaration()->symbol()) << " = " + << "param_" + std::to_string(idx++) << ";"; + make_indent(out << std::endl); + } + out << "return output;"; + + decrement_indent(); + make_indent(out << std::endl); + out << "}"; + + make_indent(out << std::endl); + + structure_builders_[str] = builder_name; + } + return true; } @@ -2469,6 +2606,63 @@ bool GeneratorImpl::EmitBlockBraces(std::ostream& out, return true; } +// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules +// TODO(crbug.com/tint/898): We need CTS and / or Dawn e2e tests for this logic. +GeneratorImpl::SizeAndAlign GeneratorImpl::HlslPackedTypeSizeAndAlign( + const sem::Type* ty) { + if (ty->IsAnyOf()) { + return {4, 4}; + } + + if (auto* vec = ty->As()) { + auto num_els = vec->size(); + auto* el_ty = vec->type(); + if (el_ty->IsAnyOf()) { + return SizeAndAlign{num_els * 4, 4}; + } + } + + if (auto* mat = ty->As()) { + auto cols = mat->columns(); + auto rows = mat->rows(); + auto* el_ty = mat->type(); + if (el_ty->IsAnyOf()) { + static constexpr SizeAndAlign table[] = { + /* float2x2 */ {16, 8}, + /* float2x3 */ {32, 16}, + /* float2x4 */ {32, 16}, + /* float3x2 */ {24, 8}, + /* float3x3 */ {48, 16}, + /* float3x4 */ {48, 16}, + /* float4x2 */ {32, 8}, + /* float4x3 */ {64, 16}, + /* float4x4 */ {64, 16}, + }; + if (cols >= 2 && cols <= 4 && rows >= 2 && rows <= 4) { + return table[(3 * (cols - 2)) + (rows - 2)]; + } + } + } + + if (auto* arr = ty->As()) { + auto el_size_align = HlslPackedTypeSizeAndAlign(arr->ElemType()); + if (!arr->IsStrideImplicit()) { + TINT_ICE(diagnostics_) << "arrays with explicit strides should have " + "removed with the PadArrayElements transform"; + return {}; + } + auto num_els = std::max(arr->Count(), 1); + return SizeAndAlign{el_size_align.size * num_els, el_size_align.align}; + } + + if (auto* str = ty->As()) { + return SizeAndAlign{str->Size(), str->Align()}; + } + + TINT_UNREACHABLE(diagnostics_) << "Unhandled type " << ty->TypeInfo().name; + return {}; +} + } // namespace hlsl } // namespace writer } // namespace tint diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h index 99dbbba62d..d14b8a10a9 100644 --- a/src/writer/hlsl/generator_impl.h +++ b/src/writer/hlsl/generator_impl.h @@ -426,8 +426,19 @@ class GeneratorImpl : public TextGenerator { return EmitBlockBraces(out, "", std::forward(cb)); } + // A pair of byte size and alignment `uint32_t`s. + struct SizeAndAlign { + uint32_t size; + uint32_t align; + }; + + /// @returns the HLSL packed type size and alignment in bytes for the given + /// type. + SizeAndAlign HlslPackedTypeSizeAndAlign(const sem::Type* ty); + ProgramBuilder builder_; std::function emit_continuing_; + std::unordered_map structure_builders_; }; } // namespace hlsl diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc index 6add088744..dc55611a1a 100644 --- a/src/writer/hlsl/generator_impl_function_test.cc +++ b/src/writer/hlsl/generator_impl_function_test.cc @@ -342,7 +342,7 @@ TEST_F(HlslGeneratorImplTest_Function, ASSERT_TRUE(gen.Generate(out)) << gen.error(); EXPECT_EQ(result(), R"(struct UBO { - float4 coord; + /* 0x0000 */ float4 coord; }; ConstantBuffer ubo : register(b0, space1); @@ -385,7 +385,7 @@ TEST_F(HlslGeneratorImplTest_Function, ASSERT_TRUE(gen.Generate(out)) << gen.error(); EXPECT_EQ(result(), R"(struct Uniforms { - float4 coord; + /* 0x0000 */ float4 coord; }; ConstantBuffer uniforms : register(b0, space1); @@ -584,7 +584,7 @@ TEST_F(HlslGeneratorImplTest_Function, ASSERT_TRUE(gen.Generate(out)) << gen.error(); EXPECT_EQ(result(), R"(struct S { - float x; + /* 0x0000 */ float x; }; ConstantBuffer coord : register(b0, space1); diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc index eb5c150f77..ac16ffe731 100644 --- a/src/writer/hlsl/generator_impl_type_test.cc +++ b/src/writer/hlsl/generator_impl_type_test.cc @@ -93,16 +93,29 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_WithoutName) { EXPECT_EQ(result(), "bool[4]"); } -TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_RuntimeArray) { - auto* arr = ty.array(); - Global("G", arr, ast::StorageClass::kPrivate); +TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayWithStride) { + auto* s = Structure("s", {Member("arr", ty.array(64))}, + {create()}); + auto* ubo = Global("ubo", ty.Of(s), ast::StorageClass::kUniform, + ast::DecorationList{ + create(1), + create(1), + }); + WrapInFunction(MemberAccessor(ubo, "arr")); - GeneratorImpl& gen = Build(); + GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), ast::StorageClass::kNone, - ast::Access::kReadWrite, "ary")) - << gen.error(); - EXPECT_EQ(result(), "bool ary[]"); + ASSERT_TRUE(gen.Generate(out)) << gen.error(); + EXPECT_THAT(result(), HasSubstr(R"(struct tint_padded_array_element { + /* 0x0000 */ float el; + /* 0x0004 */ int tint_pad_0[15]; +};)")); + EXPECT_THAT(result(), HasSubstr(R"(struct tint_array_wrapper { + /* 0x0000 */ tint_padded_array_element arr[4]; +};)")); + EXPECT_THAT(result(), HasSubstr(R"(struct s { + /* 0x0000 */ tint_array_wrapper arr; +};)")); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Bool) { @@ -219,31 +232,427 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) { EXPECT_EQ(result(), "S"); } -/// TODO(bclayton): Enable this, fix it, add tests for vector, matrix, array and -/// nested structures. -TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_InjectPadding) { - auto* s = Structure( - "S", { - Member("a", ty.i32(), {MemberSize(32)}), - Member("b", ty.f32()), - Member("c", ty.f32(), {MemberAlign(128), MemberSize(128)}), - }); - Global("g", ty.Of(s), ast::StorageClass::kPrivate); +TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_Layout_NonComposites) { + auto* s = + Structure("S", + { + Member("a", ty.i32(), {MemberSize(32)}), + Member("b", ty.f32(), {MemberAlign(128), MemberSize(128)}), + Member("c", ty.vec2()), + Member("d", ty.u32()), + Member("e", ty.vec3()), + Member("f", ty.u32()), + Member("g", ty.vec4()), + Member("h", ty.u32()), + Member("i", ty.mat2x2()), + Member("j", ty.u32()), + Member("k", ty.mat2x3()), + Member("l", ty.u32()), + Member("m", ty.mat2x4()), + Member("n", ty.u32()), + Member("o", ty.mat3x2()), + Member("p", ty.u32()), + Member("q", ty.mat3x3()), + Member("r", ty.u32()), + Member("s", ty.mat3x4()), + Member("t", ty.u32()), + Member("u", ty.mat4x2()), + Member("v", ty.u32()), + Member("w", ty.mat4x3()), + Member("x", ty.u32()), + Member("y", ty.mat4x4()), + Member("z", ty.f32()), + }, + {create()}); + + Global("G", ty.Of(s), ast::StorageClass::kUniform, + ast::DecorationList{ + create(0), + create(0), + }); GeneratorImpl& gen = Build(); auto* sem_s = program->TypeOf(s)->As(); - ASSERT_TRUE(gen.EmitType(out, sem_s, ast::StorageClass::kNone, - ast::Access::kReadWrite, "")) - << gen.error(); - EXPECT_EQ(gen.result(), R"(struct S { - int a; - int8_t pad_0[28]; - float b; - int8_t pad_1[92]; - float c; - int8_t pad_2[124]; + ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error(); + + auto* expect = R"(struct S { + /* 0x0000 */ int a; + /* 0x0004 */ int tint_pad_0[31]; + /* 0x0080 */ float b; + /* 0x0084 */ int tint_pad_1[31]; + /* 0x0100 */ float2 c; + /* 0x0108 */ uint d; + /* 0x010c */ int tint_pad_2[1]; + /* 0x0110 */ float3 e; + /* 0x011c */ uint f; + /* 0x0120 */ float4 g; + /* 0x0130 */ uint h; + /* 0x0134 */ int tint_pad_3[1]; + /* 0x0138 */ float2x2 i; + /* 0x0148 */ uint j; + /* 0x014c */ int tint_pad_4[1]; + /* 0x0150 */ float2x3 k; + /* 0x0170 */ uint l; + /* 0x0174 */ int tint_pad_5[3]; + /* 0x0180 */ float2x4 m; + /* 0x01a0 */ uint n; + /* 0x01a4 */ int tint_pad_6[1]; + /* 0x01a8 */ float3x2 o; + /* 0x01c0 */ uint p; + /* 0x01c4 */ int tint_pad_7[3]; + /* 0x01d0 */ float3x3 q; + /* 0x0200 */ uint r; + /* 0x0204 */ int tint_pad_8[3]; + /* 0x0210 */ float3x4 s; + /* 0x0240 */ uint t; + /* 0x0244 */ int tint_pad_9[1]; + /* 0x0248 */ float4x2 u; + /* 0x0268 */ uint v; + /* 0x026c */ int tint_pad_10[1]; + /* 0x0270 */ float4x3 w; + /* 0x02b0 */ uint x; + /* 0x02b4 */ int tint_pad_11[3]; + /* 0x02c0 */ float4x4 y; + /* 0x0300 */ float z; + /* 0x0304 */ int tint_pad_12[31]; }; + +S make_S(int param_0, + float param_1, + float2 param_2, + uint param_3, + float3 param_4, + uint param_5, + float4 param_6, + uint param_7, + float2x2 param_8, + uint param_9, + float2x3 param_10, + uint param_11, + float2x4 param_12, + uint param_13, + float3x2 param_14, + uint param_15, + float3x3 param_16, + uint param_17, + float3x4 param_18, + uint param_19, + float4x2 param_20, + uint param_21, + float4x3 param_22, + uint param_23, + float4x4 param_24, + float param_25) { + S output; + output.a = param_0; + output.b = param_1; + output.c = param_2; + output.d = param_3; + output.e = param_4; + output.f = param_5; + output.g = param_6; + output.h = param_7; + output.i = param_8; + output.j = param_9; + output.k = param_10; + output.l = param_11; + output.m = param_12; + output.n = param_13; + output.o = param_14; + output.p = param_15; + output.q = param_16; + output.r = param_17; + output.s = param_18; + output.t = param_19; + output.u = param_20; + output.v = param_21; + output.w = param_22; + output.x = param_23; + output.y = param_24; + output.z = param_25; + return output; +} +)"; + + EXPECT_EQ(result(), expect); +} + +TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_Layout_Structures) { + // inner_x: size(1024), align(512) + auto* inner_x = + Structure("inner_x", { + Member("a", ty.i32()), + Member("b", ty.f32(), {MemberAlign(512)}), + }); + + // inner_y: size(516), align(4) + auto* inner_y = + Structure("inner_y", { + Member("a", ty.i32(), {MemberSize(512)}), + Member("b", ty.f32()), + }); + + auto* s = Structure("S", + { + Member("a", ty.i32()), + Member("b", ty.Of(inner_x)), + Member("c", ty.f32()), + Member("d", ty.Of(inner_y)), + Member("e", ty.f32()), + }, + {create()}); + + Global("G", ty.Of(s), ast::StorageClass::kUniform, + ast::DecorationList{ + create(0), + create(0), + }); + + GeneratorImpl& gen = Build(); + + auto* sem_s = program->TypeOf(s)->As(); + ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error(); + + auto* expect = R"(struct S { + /* 0x0000 */ int a; + /* 0x0004 */ int tint_pad_0[127]; + /* 0x0200 */ inner_x b; + /* 0x0600 */ float c; + /* 0x0604 */ inner_y d; + /* 0x0808 */ float e; + /* 0x080c */ int tint_pad_1[125]; +}; + +S make_S(int param_0, + inner_x param_1, + float param_2, + inner_y param_3, + float param_4) { + S output; + output.a = param_0; + output.b = param_1; + output.c = param_2; + output.d = param_3; + output.e = param_4; + return output; +} +)"; + EXPECT_EQ(result(), expect); +} + +TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_Layout_ArrayDefaultStride) { + // inner: size(1024), align(512) + auto* inner = + Structure("inner", { + Member("a", ty.i32()), + Member("b", ty.f32(), {MemberAlign(512)}), + }); + + // array_x: size(28), align(4) + auto* array_x = ty.array(); + + // array_y: size(4096), align(512) + auto* array_y = ty.array(ty.Of(inner), 4); + + // array_z: size(4), align(4) + auto* array_z = ty.array(); + + auto* s = + Structure("S", + { + Member("a", ty.i32()), + Member("b", array_x), + Member("c", ty.f32()), + Member("d", array_y), + Member("e", ty.f32()), + Member("f", array_z), + }, + ast::DecorationList{create()}); + + Global("G", ty.Of(s), ast::StorageClass::kUniform, + ast::DecorationList{ + create(0), + create(0), + }); + + GeneratorImpl& gen = Build(); + + auto* sem_s = program->TypeOf(s)->As(); + ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error(); + + auto* expect = R"(struct S { + /* 0x0000 */ int a; + /* 0x0004 */ float b[7]; + /* 0x0020 */ float c; + /* 0x0024 */ int tint_pad_0[119]; + /* 0x0200 */ inner d[4]; + /* 0x1200 */ float e; + /* 0x1204 */ float f[1]; + /* 0x1208 */ int tint_pad_1[126]; +}; + +S make_S(int param_0, + float param_1[7], + float param_2, + inner param_3[4], + float param_4, + float param_5[1]) { + S output; + output.a = param_0; + output.b = param_1; + output.c = param_2; + output.d = param_3; + output.e = param_4; + output.f = param_5; + return output; +} +)"; + + EXPECT_EQ(result(), expect); +} + +TEST_F(HlslGeneratorImplTest_Type, AttemptTintPadSymbolCollision) { + auto* s = Structure( + "S", + { + // uses symbols tint_pad_[0..9] and tint_pad_[20..35] + Member("tint_pad_2", ty.i32(), {MemberSize(32)}), + Member("tint_pad_20", ty.f32(), {MemberAlign(128), MemberSize(128)}), + Member("tint_pad_33", ty.vec2()), + Member("tint_pad_1", ty.u32()), + Member("tint_pad_3", ty.vec3()), + Member("tint_pad_7", ty.u32()), + Member("tint_pad_25", ty.vec4()), + Member("tint_pad_5", ty.u32()), + Member("tint_pad_27", ty.mat2x2()), + Member("tint_pad_24", ty.u32()), + Member("tint_pad_23", ty.mat2x3()), + Member("tint_pad_0", ty.u32()), + Member("tint_pad_8", ty.mat2x4()), + Member("tint_pad_26", ty.u32()), + Member("tint_pad_29", ty.mat3x2()), + Member("tint_pad_6", ty.u32()), + Member("tint_pad_22", ty.mat3x3()), + Member("tint_pad_32", ty.u32()), + Member("tint_pad_34", ty.mat3x4()), + Member("tint_pad_35", ty.u32()), + Member("tint_pad_30", ty.mat4x2()), + Member("tint_pad_9", ty.u32()), + Member("tint_pad_31", ty.mat4x3()), + Member("tint_pad_28", ty.u32()), + Member("tint_pad_4", ty.mat4x4()), + Member("tint_pad_21", ty.f32()), + }, + {create()}); + + Global("G", ty.Of(s), ast::StorageClass::kUniform, + ast::DecorationList{ + create(0), + create(0), + }); + + GeneratorImpl& gen = Build(); + + auto* sem_s = program->TypeOf(s)->As(); + ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error(); + EXPECT_EQ(result(), R"(struct S { + /* 0x0000 */ int tint_pad_2; + /* 0x0004 */ int tint_pad_10[31]; + /* 0x0080 */ float tint_pad_20; + /* 0x0084 */ int tint_pad_11[31]; + /* 0x0100 */ float2 tint_pad_33; + /* 0x0108 */ uint tint_pad_1; + /* 0x010c */ int tint_pad_12[1]; + /* 0x0110 */ float3 tint_pad_3; + /* 0x011c */ uint tint_pad_7; + /* 0x0120 */ float4 tint_pad_25; + /* 0x0130 */ uint tint_pad_5; + /* 0x0134 */ int tint_pad_13[1]; + /* 0x0138 */ float2x2 tint_pad_27; + /* 0x0148 */ uint tint_pad_24; + /* 0x014c */ int tint_pad_14[1]; + /* 0x0150 */ float2x3 tint_pad_23; + /* 0x0170 */ uint tint_pad_0; + /* 0x0174 */ int tint_pad_15[3]; + /* 0x0180 */ float2x4 tint_pad_8; + /* 0x01a0 */ uint tint_pad_26; + /* 0x01a4 */ int tint_pad_16[1]; + /* 0x01a8 */ float3x2 tint_pad_29; + /* 0x01c0 */ uint tint_pad_6; + /* 0x01c4 */ int tint_pad_17[3]; + /* 0x01d0 */ float3x3 tint_pad_22; + /* 0x0200 */ uint tint_pad_32; + /* 0x0204 */ int tint_pad_18[3]; + /* 0x0210 */ float3x4 tint_pad_34; + /* 0x0240 */ uint tint_pad_35; + /* 0x0244 */ int tint_pad_19[1]; + /* 0x0248 */ float4x2 tint_pad_30; + /* 0x0268 */ uint tint_pad_9; + /* 0x026c */ int tint_pad_36[1]; + /* 0x0270 */ float4x3 tint_pad_31; + /* 0x02b0 */ uint tint_pad_28; + /* 0x02b4 */ int tint_pad_37[3]; + /* 0x02c0 */ float4x4 tint_pad_4; + /* 0x0300 */ float tint_pad_21; + /* 0x0304 */ int tint_pad_38[31]; +}; + +S make_S(int param_0, + float param_1, + float2 param_2, + uint param_3, + float3 param_4, + uint param_5, + float4 param_6, + uint param_7, + float2x2 param_8, + uint param_9, + float2x3 param_10, + uint param_11, + float2x4 param_12, + uint param_13, + float3x2 param_14, + uint param_15, + float3x3 param_16, + uint param_17, + float3x4 param_18, + uint param_19, + float4x2 param_20, + uint param_21, + float4x3 param_22, + uint param_23, + float4x4 param_24, + float param_25) { + S output; + output.tint_pad_2 = param_0; + output.tint_pad_20 = param_1; + output.tint_pad_33 = param_2; + output.tint_pad_1 = param_3; + output.tint_pad_3 = param_4; + output.tint_pad_7 = param_5; + output.tint_pad_25 = param_6; + output.tint_pad_5 = param_7; + output.tint_pad_27 = param_8; + output.tint_pad_24 = param_9; + output.tint_pad_23 = param_10; + output.tint_pad_0 = param_11; + output.tint_pad_8 = param_12; + output.tint_pad_26 = param_13; + output.tint_pad_29 = param_14; + output.tint_pad_6 = param_15; + output.tint_pad_22 = param_16; + output.tint_pad_32 = param_17; + output.tint_pad_34 = param_18; + output.tint_pad_35 = param_19; + output.tint_pad_30 = param_20; + output.tint_pad_9 = param_21; + output.tint_pad_31 = param_22; + output.tint_pad_28 = param_23; + output.tint_pad_4 = param_24; + output.tint_pad_21 = param_25; + return output; +} )"); } diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc index ecd920574a..d6ffed25c1 100644 --- a/src/writer/msl/generator_impl.cc +++ b/src/writer/msl/generator_impl.cc @@ -2410,6 +2410,7 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { return true; } +// TODO(crbug.com/tint/898): We need CTS and / or Dawn e2e tests for this logic. GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign( const sem::Type* ty) { if (ty->IsAnyOf()) { diff --git a/test/array/assign_to_function_var.wgsl.expected.hlsl b/test/array/assign_to_function_var.wgsl.expected.hlsl index 6722f05497..5935a13e61 100644 --- a/test/array/assign_to_function_var.wgsl.expected.hlsl +++ b/test/array/assign_to_function_var.wgsl.expected.hlsl @@ -4,17 +4,24 @@ void unused_entry_point() { } struct tint_padded_array_element { - int el; + /* 0x0000 */ int el; + /* 0x0004 */ int tint_pad_0[3]; }; + +tint_padded_array_element make_tint_padded_array_element(int param_0) { + tint_padded_array_element output; + output.el = param_0; + return output; +} struct tint_array_wrapper { - tint_padded_array_element arr[4]; + /* 0x0000 */ tint_padded_array_element arr[4]; }; struct S { - tint_array_wrapper arr; + /* 0x0000 */ tint_array_wrapper arr; }; tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) { - const tint_array_wrapper tint_symbol_3 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}}; + const tint_array_wrapper tint_symbol_3 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}}; return tint_symbol_3; } @@ -24,12 +31,12 @@ ConstantBuffer src_uniform : register(b0, space0); RWByteAddressBuffer src_storage : register(u1, space0); tint_array_wrapper ret_arr() { - const tint_array_wrapper tint_symbol_4 = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper tint_symbol_4 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; return tint_symbol_4; } S ret_struct_arr() { - const S tint_symbol_5 = {{{{0}, {0}, {0}, {0}}}}; + const S tint_symbol_5 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}}; return tint_symbol_5; } @@ -44,13 +51,13 @@ struct tint_array_wrapper_1 { }; void foo(tint_array_wrapper src_param) { - tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}}; - tint_array_wrapper tint_symbol = {{{0}, {0}, {0}, {0}}}; - const tint_array_wrapper tint_symbol_6 = {{{1}, {2}, {3}, {3}}}; + tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; + tint_array_wrapper tint_symbol = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; + const tint_array_wrapper tint_symbol_6 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}}; tint_symbol = tint_symbol_6; tint_symbol = src_param; tint_symbol = ret_arr(); - const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; tint_symbol = src_let; tint_symbol = src_function; tint_symbol = src_private; diff --git a/test/array/assign_to_private_var.wgsl.expected.hlsl b/test/array/assign_to_private_var.wgsl.expected.hlsl index 8f935d44c5..cca7ff685d 100644 --- a/test/array/assign_to_private_var.wgsl.expected.hlsl +++ b/test/array/assign_to_private_var.wgsl.expected.hlsl @@ -4,17 +4,24 @@ void unused_entry_point() { } struct tint_padded_array_element { - int el; + /* 0x0000 */ int el; + /* 0x0004 */ int tint_pad_0[3]; }; + +tint_padded_array_element make_tint_padded_array_element(int param_0) { + tint_padded_array_element output; + output.el = param_0; + return output; +} struct tint_array_wrapper { - tint_padded_array_element arr[4]; + /* 0x0000 */ tint_padded_array_element arr[4]; }; struct S { - tint_array_wrapper arr; + /* 0x0000 */ tint_array_wrapper arr; }; tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) { - const tint_array_wrapper tint_symbol_3 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}}; + const tint_array_wrapper tint_symbol_3 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}}; return tint_symbol_3; } @@ -37,22 +44,22 @@ struct tint_array_wrapper_1 { static tint_array_wrapper_1 dst_nested; tint_array_wrapper ret_arr() { - const tint_array_wrapper tint_symbol_4 = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper tint_symbol_4 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; return tint_symbol_4; } S ret_struct_arr() { - const S tint_symbol_5 = {{{{0}, {0}, {0}, {0}}}}; + const S tint_symbol_5 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}}; return tint_symbol_5; } void foo(tint_array_wrapper src_param) { - tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}}; - const tint_array_wrapper tint_symbol_6 = {{{1}, {2}, {3}, {3}}}; + tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; + const tint_array_wrapper tint_symbol_6 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}}; tint_symbol = tint_symbol_6; tint_symbol = src_param; tint_symbol = ret_arr(); - const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; tint_symbol = src_let; tint_symbol = src_function; tint_symbol = src_private; diff --git a/test/array/assign_to_storage_var.wgsl.expected.hlsl b/test/array/assign_to_storage_var.wgsl.expected.hlsl index 6988ce280e..6ed5129a2a 100644 --- a/test/array/assign_to_storage_var.wgsl.expected.hlsl +++ b/test/array/assign_to_storage_var.wgsl.expected.hlsl @@ -4,17 +4,24 @@ void unused_entry_point() { } struct tint_padded_array_element { - int el; + /* 0x0000 */ int el; + /* 0x0004 */ int tint_pad_0[3]; }; + +tint_padded_array_element make_tint_padded_array_element(int param_0) { + tint_padded_array_element output; + output.el = param_0; + return output; +} struct tint_array_wrapper { - tint_padded_array_element arr[4]; + /* 0x0000 */ tint_padded_array_element arr[4]; }; struct S { - tint_array_wrapper arr; + /* 0x0000 */ tint_array_wrapper arr; }; tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) { - const tint_array_wrapper tint_symbol_9 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}}; + const tint_array_wrapper tint_symbol_9 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}}; return tint_symbol_9; } @@ -26,13 +33,13 @@ void tint_symbol_4(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper v } struct tint_array_wrapper_3 { - int arr[2]; + /* 0x0000 */ int arr[2]; }; struct tint_array_wrapper_2 { - tint_array_wrapper_3 arr[3]; + /* 0x0000 */ tint_array_wrapper_3 arr[3]; }; struct tint_array_wrapper_1 { - tint_array_wrapper_2 arr[4]; + /* 0x0000 */ tint_array_wrapper_2 arr[4]; }; void tint_symbol_6(RWByteAddressBuffer buffer, uint offset, tint_array_wrapper_3 value) { @@ -61,22 +68,22 @@ RWByteAddressBuffer tint_symbol : register(u2, space0); RWByteAddressBuffer dst_nested : register(u3, space0); tint_array_wrapper ret_arr() { - const tint_array_wrapper tint_symbol_10 = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper tint_symbol_10 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; return tint_symbol_10; } S ret_struct_arr() { - const S tint_symbol_11 = {{{{0}, {0}, {0}, {0}}}}; + const S tint_symbol_11 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}}; return tint_symbol_11; } void foo(tint_array_wrapper src_param) { - tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}}; - const tint_array_wrapper tint_symbol_12 = {{{1}, {2}, {3}, {3}}}; + tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; + const tint_array_wrapper tint_symbol_12 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}}; tint_symbol_4(tint_symbol, 0u, tint_symbol_12); tint_symbol_4(tint_symbol, 0u, src_param); tint_symbol_4(tint_symbol, 0u, ret_arr()); - const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; tint_symbol_4(tint_symbol, 0u, src_let); tint_symbol_4(tint_symbol, 0u, src_function); tint_symbol_4(tint_symbol, 0u, src_private); diff --git a/test/array/assign_to_workgroup_var.wgsl.expected.hlsl b/test/array/assign_to_workgroup_var.wgsl.expected.hlsl index 725566e72d..64bb639958 100644 --- a/test/array/assign_to_workgroup_var.wgsl.expected.hlsl +++ b/test/array/assign_to_workgroup_var.wgsl.expected.hlsl @@ -4,17 +4,24 @@ void unused_entry_point() { } struct tint_padded_array_element { - int el; + /* 0x0000 */ int el; + /* 0x0004 */ int tint_pad_0[3]; }; + +tint_padded_array_element make_tint_padded_array_element(int param_0) { + tint_padded_array_element output; + output.el = param_0; + return output; +} struct tint_array_wrapper { - tint_padded_array_element arr[4]; + /* 0x0000 */ tint_padded_array_element arr[4]; }; struct S { - tint_array_wrapper arr; + /* 0x0000 */ tint_array_wrapper arr; }; tint_array_wrapper tint_symbol_2(RWByteAddressBuffer buffer, uint offset) { - const tint_array_wrapper tint_symbol_3 = {{{asint(buffer.Load((offset + 0u)))}, {asint(buffer.Load((offset + 16u)))}, {asint(buffer.Load((offset + 32u)))}, {asint(buffer.Load((offset + 48u)))}}}; + const tint_array_wrapper tint_symbol_3 = {{make_tint_padded_array_element(asint(buffer.Load((offset + 0u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 16u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 32u)))), make_tint_padded_array_element(asint(buffer.Load((offset + 48u))))}}; return tint_symbol_3; } @@ -37,22 +44,22 @@ struct tint_array_wrapper_1 { groupshared tint_array_wrapper_1 dst_nested; tint_array_wrapper ret_arr() { - const tint_array_wrapper tint_symbol_4 = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper tint_symbol_4 = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; return tint_symbol_4; } S ret_struct_arr() { - const S tint_symbol_5 = {{{{0}, {0}, {0}, {0}}}}; + const S tint_symbol_5 = {{{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}}; return tint_symbol_5; } void foo(tint_array_wrapper src_param) { - tint_array_wrapper src_function = {{{0}, {0}, {0}, {0}}}; - const tint_array_wrapper tint_symbol_6 = {{{1}, {2}, {3}, {3}}}; + tint_array_wrapper src_function = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; + const tint_array_wrapper tint_symbol_6 = {{make_tint_padded_array_element(1), make_tint_padded_array_element(2), make_tint_padded_array_element(3), make_tint_padded_array_element(3)}}; tint_symbol = tint_symbol_6; tint_symbol = src_param; tint_symbol = ret_arr(); - const tint_array_wrapper src_let = {{{0}, {0}, {0}, {0}}}; + const tint_array_wrapper src_let = {{make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0), make_tint_padded_array_element(0)}}; tint_symbol = src_let; tint_symbol = src_function; tint_symbol = src_private; diff --git a/test/bug/tint/744.wgsl.expected.hlsl b/test/bug/tint/744.wgsl.expected.hlsl index d6842146f0..7819eb6611 100644 --- a/test/bug/tint/744.wgsl.expected.hlsl +++ b/test/bug/tint/744.wgsl.expected.hlsl @@ -1,7 +1,7 @@ struct Uniforms { - uint2 aShape; - uint2 bShape; - uint2 outShape; + /* 0x0000 */ uint2 aShape; + /* 0x0008 */ uint2 bShape; + /* 0x0010 */ uint2 outShape; }; ByteAddressBuffer firstMatrix : register(t0, space0); diff --git a/test/bug/tint/757.wgsl.expected.hlsl b/test/bug/tint/757.wgsl.expected.hlsl index 63d2e80ddf..e7db5923ad 100644 --- a/test/bug/tint/757.wgsl.expected.hlsl +++ b/test/bug/tint/757.wgsl.expected.hlsl @@ -1,5 +1,5 @@ struct Constants { - int level; + /* 0x0000 */ int level; }; ConstantBuffer constants : register(b0, space0); diff --git a/test/bug/tint/870.spvasm.expected.hlsl b/test/bug/tint/870.spvasm.expected.hlsl index e46584087c..56649a2ecc 100644 --- a/test/bug/tint/870.spvasm.expected.hlsl +++ b/test/bug/tint/870.spvasm.expected.hlsl @@ -1,5 +1,5 @@ struct tint_array_wrapper { - int arr[6]; + /* 0x0000 */ int arr[6]; }; tint_array_wrapper tint_symbol_1(ByteAddressBuffer buffer, uint offset) { diff --git a/test/ptr_ref/load/local/ptr_uniform.wgsl.expected.hlsl b/test/ptr_ref/load/local/ptr_uniform.wgsl.expected.hlsl index f0642c7104..ac3efc54a3 100644 --- a/test/ptr_ref/load/local/ptr_uniform.wgsl.expected.hlsl +++ b/test/ptr_ref/load/local/ptr_uniform.wgsl.expected.hlsl @@ -1,5 +1,5 @@ struct S { - int a; + /* 0x0000 */ int a; }; ConstantBuffer v : register(b0, space0); diff --git a/test/samples/compute_boids.wgsl.expected.hlsl b/test/samples/compute_boids.wgsl.expected.hlsl index ab102f4862..974996a4a4 100644 --- a/test/samples/compute_boids.wgsl.expected.hlsl +++ b/test/samples/compute_boids.wgsl.expected.hlsl @@ -27,13 +27,13 @@ tint_symbol_3 frag_main() { } struct SimParams { - float deltaT; - float rule1Distance; - float rule2Distance; - float rule3Distance; - float rule1Scale; - float rule2Scale; - float rule3Scale; + /* 0x0000 */ float deltaT; + /* 0x0004 */ float rule1Distance; + /* 0x0008 */ float rule2Distance; + /* 0x000c */ float rule3Distance; + /* 0x0010 */ float rule1Scale; + /* 0x0014 */ float rule2Scale; + /* 0x0018 */ float rule3Scale; }; ConstantBuffer params : register(b0, space0); diff --git a/test/samples/cube.wgsl.expected.hlsl b/test/samples/cube.wgsl.expected.hlsl index bae4c7ef6f..05fb49f6ef 100644 --- a/test/samples/cube.wgsl.expected.hlsl +++ b/test/samples/cube.wgsl.expected.hlsl @@ -1,5 +1,5 @@ struct Uniforms { - float4x4 modelViewProjectionMatrix; + /* 0x0000 */ float4x4 modelViewProjectionMatrix; }; ConstantBuffer uniforms : register(b0, space0); diff --git a/test/shader_io/shared_struct_storage_buffer.wgsl.expected.hlsl b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.hlsl index 1c8ad7dfb8..b4822054a5 100644 --- a/test/shader_io/shared_struct_storage_buffer.wgsl.expected.hlsl +++ b/test/shader_io/shared_struct_storage_buffer.wgsl.expected.hlsl @@ -1,9 +1,21 @@ struct S { - float f; - uint u; - float4 v; + /* 0x0000 */ float f; + /* 0x0004 */ uint u; + /* 0x0008 */ int tint_pad_0[30]; + /* 0x0080 */ float4 v; + /* 0x0090 */ int tint_pad_1[28]; }; +S make_S(float param_0, + uint param_1, + float4 param_2) { + S output; + output.f = param_0; + output.u = param_1; + output.v = param_2; + return output; +} + void tint_symbol_5(RWByteAddressBuffer buffer, uint offset, S value) { buffer.Store((offset + 0u), asuint(value.f)); buffer.Store((offset + 4u), asuint(value.u)); @@ -19,7 +31,7 @@ struct tint_symbol_1 { }; void frag_main(tint_symbol_1 tint_symbol) { - const S input = {tint_symbol.f, tint_symbol.u, tint_symbol.v}; + const S input = make_S(tint_symbol.f, tint_symbol.u, tint_symbol.v); const float f = input.f; const uint u = input.u; const float4 v = input.v;