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 <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2021-06-16 09:50:11 +00:00 committed by Ben Clayton
parent 31936f375f
commit d47eb3a965
16 changed files with 756 additions and 101 deletions

View File

@ -14,6 +14,8 @@
#include "src/writer/hlsl/generator_impl.h"
#include <algorithm>
#include <iomanip>
#include <utility>
#include <vector>
@ -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<sem::Struct>(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<sem::Struct>()) {
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<sem::Array>()) {
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<sem::Array>()) {
out << " " << mem_name;
if (!ty->Is<sem::Array>()) {
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<sem::Array>()) {
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<sem::U32, sem::I32, sem::F32>()) {
return {4, 4};
}
if (auto* vec = ty->As<sem::Vector>()) {
auto num_els = vec->size();
auto* el_ty = vec->type();
if (el_ty->IsAnyOf<sem::U32, sem::I32, sem::F32>()) {
return SizeAndAlign{num_els * 4, 4};
}
}
if (auto* mat = ty->As<sem::Matrix>()) {
auto cols = mat->columns();
auto rows = mat->rows();
auto* el_ty = mat->type();
if (el_ty->IsAnyOf<sem::U32, sem::I32, sem::F32>()) {
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<sem::Array>()) {
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<uint32_t>(arr->Count(), 1);
return SizeAndAlign{el_size_align.size * num_els, el_size_align.align};
}
if (auto* str = ty->As<sem::Struct>()) {
return SizeAndAlign{str->Size(), str->Align()};
}
TINT_UNREACHABLE(diagnostics_) << "Unhandled type " << ty->TypeInfo().name;
return {};
}
} // namespace hlsl
} // namespace writer
} // namespace tint

View File

@ -426,8 +426,19 @@ class GeneratorImpl : public TextGenerator {
return EmitBlockBraces(out, "", std::forward<F>(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<bool(std::ostream& out)> emit_continuing_;
std::unordered_map<const sem::Struct*, std::string> structure_builders_;
};
} // namespace hlsl

View File

@ -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> 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> 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<S> coord : register(b0, space1);

View File

@ -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<bool>();
Global("G", arr, ast::StorageClass::kPrivate);
TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayWithStride) {
auto* s = Structure("s", {Member("arr", ty.array<f32, 4>(64))},
{create<ast::StructBlockDecoration>()});
auto* ubo = Global("ubo", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{
create<ast::GroupDecoration>(1),
create<ast::BindingDecoration>(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<f32>()),
Member("d", ty.u32()),
Member("e", ty.vec3<f32>()),
Member("f", ty.u32()),
Member("g", ty.vec4<f32>()),
Member("h", ty.u32()),
Member("i", ty.mat2x2<f32>()),
Member("j", ty.u32()),
Member("k", ty.mat2x3<f32>()),
Member("l", ty.u32()),
Member("m", ty.mat2x4<f32>()),
Member("n", ty.u32()),
Member("o", ty.mat3x2<f32>()),
Member("p", ty.u32()),
Member("q", ty.mat3x3<f32>()),
Member("r", ty.u32()),
Member("s", ty.mat3x4<f32>()),
Member("t", ty.u32()),
Member("u", ty.mat4x2<f32>()),
Member("v", ty.u32()),
Member("w", ty.mat4x3<f32>()),
Member("x", ty.u32()),
Member("y", ty.mat4x4<f32>()),
Member("z", ty.f32()),
},
{create<ast::StructBlockDecoration>()});
Global("G", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{
create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0),
});
GeneratorImpl& gen = Build();
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
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<ast::StructBlockDecoration>()});
Global("G", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{
create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0),
});
GeneratorImpl& gen = Build();
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
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<f32, 7>();
// 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<f32, 1>();
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<ast::StructBlockDecoration>()});
Global("G", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{
create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0),
});
GeneratorImpl& gen = Build();
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
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<f32>()),
Member("tint_pad_1", ty.u32()),
Member("tint_pad_3", ty.vec3<f32>()),
Member("tint_pad_7", ty.u32()),
Member("tint_pad_25", ty.vec4<f32>()),
Member("tint_pad_5", ty.u32()),
Member("tint_pad_27", ty.mat2x2<f32>()),
Member("tint_pad_24", ty.u32()),
Member("tint_pad_23", ty.mat2x3<f32>()),
Member("tint_pad_0", ty.u32()),
Member("tint_pad_8", ty.mat2x4<f32>()),
Member("tint_pad_26", ty.u32()),
Member("tint_pad_29", ty.mat3x2<f32>()),
Member("tint_pad_6", ty.u32()),
Member("tint_pad_22", ty.mat3x3<f32>()),
Member("tint_pad_32", ty.u32()),
Member("tint_pad_34", ty.mat3x4<f32>()),
Member("tint_pad_35", ty.u32()),
Member("tint_pad_30", ty.mat4x2<f32>()),
Member("tint_pad_9", ty.u32()),
Member("tint_pad_31", ty.mat4x3<f32>()),
Member("tint_pad_28", ty.u32()),
Member("tint_pad_4", ty.mat4x4<f32>()),
Member("tint_pad_21", ty.f32()),
},
{create<ast::StructBlockDecoration>()});
Global("G", ty.Of(s), ast::StorageClass::kUniform,
ast::DecorationList{
create<ast::BindingDecoration>(0),
create<ast::GroupDecoration>(0),
});
GeneratorImpl& gen = Build();
auto* sem_s = program->TypeOf(s)->As<sem::Struct>();
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;
}
)");
}

View File

@ -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<sem::U32, sem::I32, sem::F32>()) {

View File

@ -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<S> 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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -1,5 +1,5 @@
struct Constants {
int level;
/* 0x0000 */ int level;
};
ConstantBuffer<Constants> constants : register(b0, space0);

View File

@ -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) {

View File

@ -1,5 +1,5 @@
struct S {
int a;
/* 0x0000 */ int a;
};
ConstantBuffer<S> v : register(b0, space0);

View File

@ -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<SimParams> params : register(b0, space0);

View File

@ -1,5 +1,5 @@
struct Uniforms {
float4x4 modelViewProjectionMatrix;
/* 0x0000 */ float4x4 modelViewProjectionMatrix;
};
ConstantBuffer<Uniforms> uniforms : register(b0, space0);

View File

@ -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;