summaryrefslogtreecommitdiffstats
path: root/tests/language-feature
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2025-07-31 15:23:13 +0800
committerGitHub <noreply@github.com>2025-07-31 07:23:13 +0000
commit66301ab9068c5705e5a2bcbf2eaadfb28e8bb084 (patch)
tree3682e0224df6706bcf70f58e37873c1d078c785c /tests/language-feature
parentdb59c22cfb774e984a207a074f13870b78ec0071 (diff)
msvc style bitfield packing (#7963)
Closes https://github.com/shader-slang/slang/issues/3646 New tests rather than just adding another TEST line to existing tests so that we get the msvc- prefix in the output of slang-test
Diffstat (limited to 'tests/language-feature')
-rw-r--r--tests/language-feature/bitfield/msvc-mixed.slang40
-rw-r--r--tests/language-feature/bitfield/msvc-repr-mixed.slang38
-rw-r--r--tests/language-feature/bitfield/msvc-repr.slang36
-rw-r--r--tests/language-feature/bitfield/msvc-simple.slang31
-rw-r--r--tests/language-feature/bitfield/msvc-sizeof.slang43
-rw-r--r--tests/language-feature/bitfield/msvc-zero-width.slang30
-rw-r--r--tests/language-feature/bitfield/repr-mixed.slang36
-rw-r--r--tests/language-feature/bitfield/repr.slang36
8 files changed, 290 insertions, 0 deletions
diff --git a/tests/language-feature/bitfield/msvc-mixed.slang b/tests/language-feature/bitfield/msvc-mixed.slang
new file mode 100644
index 000000000..d21bdad37
--- /dev/null
+++ b/tests/language-feature/bitfield/msvc-mixed.slang
@@ -0,0 +1,40 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu -output-using-type -compile-arg -msvc-style-bitfield-packing
+
+// MSVC packing with mixed type sizes
+// CHECK: 15
+// CHECK-NEXT: 255
+// CHECK-NEXT: 4095
+// CHECK-NEXT: 8
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct MixedTypes {
+ uint8_t a : 4; // Uses uint8_t backing, bits 7-4
+ uint8_t b : 4; // Same backing, bits 3-0
+ uint16_t c : 8; // New uint16_t backing due to type change, bits 15-8
+ uint16_t d : 8; // Same backing, bits 7-0
+ uint32_t e : 12; // New uint32_t backing due to type change, bits 31-20
+ uint32_t f : 12; // Same backing, bits 19-8
+ uint32_t g : 8; // Same backing, bits 7-0
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ MixedTypes m;
+ m.a = 15; // 0xF
+ m.b = 15; // 0xF
+ m.c = 255; // 0xFF
+ m.d = 255; // 0xFF
+ m.e = 4095; // 0xFFF
+ m.f = 4095; // 0xFFF
+ m.g = 255; // 0xFF
+
+ outputBuffer[0] = m.a;
+ outputBuffer[1] = m.c;
+ outputBuffer[2] = m.e;
+ // Verify struct size includes all three backing fields
+ outputBuffer[3] = sizeof(MixedTypes);
+}
+
diff --git a/tests/language-feature/bitfield/msvc-repr-mixed.slang b/tests/language-feature/bitfield/msvc-repr-mixed.slang
new file mode 100644
index 000000000..47f03ad1d
--- /dev/null
+++ b/tests/language-feature/bitfield/msvc-repr-mixed.slang
@@ -0,0 +1,38 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu -compile-arg -msvc-style-bitfield-packing
+
+// MSVC creates separate backing fields for different type sizes
+// struct MixedSizes { uint8_t a:4; uint8_t b:4; uint16_t c:8; uint16_t d:8; }
+// First backing (uint8_t): a=0xA (bits 4-7), b=0xB (bits 0-3) => 0xAB
+// Second backing (uint16_t): c=0xCD (bits 8-15), d=0xEF (bits 0-7) => 0xCDEF
+// Memory layout: [0xAB, padding, 0xCDEF] or [0xAB, padding, 0xEF, 0xCD] depending on endianness
+
+// CHECK: AB
+// CHECK-NEXT: CDEF
+
+//TEST_INPUT:ubuffer(data=[0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct MixedSizes {
+ uint8_t a : 4; // First backing field (uint8_t)
+ uint8_t b : 4; // Same backing field
+ uint16_t c : 8; // New backing field (uint16_t) due to type change
+ uint16_t d : 8; // Same backing field
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ MixedSizes m;
+ m.a = 0xA;
+ m.b = 0xB;
+ m.c = 0xCD;
+ m.d = 0xEF;
+
+ // Read the two backing fields separately
+ uint8_t* p8 = (uint8_t*)&m;
+ uint16_t* p16 = (uint16_t*)((uint8_t*)&m + 2); // Skip uint8_t + padding
+
+ outputBuffer[0] = uint(*p8);
+ outputBuffer[1] = uint(*p16);
+}
+
diff --git a/tests/language-feature/bitfield/msvc-repr.slang b/tests/language-feature/bitfield/msvc-repr.slang
new file mode 100644
index 000000000..4edd47556
--- /dev/null
+++ b/tests/language-feature/bitfield/msvc-repr.slang
@@ -0,0 +1,36 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu -compile-arg -msvc-style-bitfield-packing
+
+// MSVC style packs from MSB to LSB
+// struct S { uint a:4; uint b:8; uint c:4; uint d:16; }
+// Memory layout (32-bit):
+// bits 28-31: a (0x5)
+// bits 20-27: b (0xAB)
+// bits 16-19: c (0xC)
+// bits 0-15: d (0xDEF0)
+// Expected: 0x5ABCDEF0
+
+// CHECK: 5ABCDEF0
+
+//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct S {
+ uint a : 4; // bits 28-31 (MSB side)
+ uint b : 8; // bits 20-27
+ uint c : 4; // bits 16-19
+ uint d : 16; // bits 0-15
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ S s;
+ s.a = 0x5;
+ s.b = 0xAB;
+ s.c = 0xC;
+ s.d = 0xDEF0;
+
+ // Write the struct to memory and read it back as uint
+ outputBuffer[0] = *((uint*)&s);
+}
+
diff --git a/tests/language-feature/bitfield/msvc-simple.slang b/tests/language-feature/bitfield/msvc-simple.slang
new file mode 100644
index 000000000..4651626b8
--- /dev/null
+++ b/tests/language-feature/bitfield/msvc-simple.slang
@@ -0,0 +1,31 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu -output-using-type -compile-arg -msvc-style-bitfield-packing
+
+// With MSVC packing, bitfields are packed from MSB to LSB
+// and new backing fields start when type sizes change
+// CHECK: 123
+// CHECK-NEXT: 4567
+// CHECK-NEXT: 0
+// CHECK-NEXT: 0
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct S {
+ int foo : 8; // Packed in bits 31-24
+ uint bar : 24; // Packed in bits 23-0
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ S s;
+ s.foo = 123;
+ s.bar = 4567;
+ outputBuffer[0] = s.foo;
+ outputBuffer[1] = s.bar;
+ s.foo = 0;
+ s.bar = 0;
+ outputBuffer[2] = s.foo;
+ outputBuffer[3] = s.bar;
+}
+
diff --git a/tests/language-feature/bitfield/msvc-sizeof.slang b/tests/language-feature/bitfield/msvc-sizeof.slang
new file mode 100644
index 000000000..9d4ccdcfc
--- /dev/null
+++ b/tests/language-feature/bitfield/msvc-sizeof.slang
@@ -0,0 +1,43 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu -output-using-type -compile-arg -msvc-style-bitfield-packing
+
+// MSVC starts new backing fields when type sizes change
+// CHECK: 4
+// CHECK-NEXT: 12
+// CHECK-NEXT: 8
+// CHECK-NEXT: 16
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct S {
+ int foo : 8;
+ int bar : 24;
+};
+
+// MSVC will use separate backing fields for different sized types
+struct T {
+ int64_t foo : 33; // Uses int64_t backing
+ int bar : 24; // Uses separate int backing due to type size change
+};
+
+// This still takes two ints to store all the bits
+struct P {
+ int foo : 24;
+ int bar : 24;
+};
+
+// MSVC will use separate backing fields due to type size difference
+struct Q {
+ int8_t foo : 1; // Uses int8_t backing
+ int64_t bar : 63; // Uses separate int64_t backing
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ outputBuffer[0] = sizeof(S);
+ outputBuffer[1] = sizeof(T);
+ outputBuffer[2] = sizeof(P);
+ outputBuffer[3] = sizeof(Q);
+}
+
diff --git a/tests/language-feature/bitfield/msvc-zero-width.slang b/tests/language-feature/bitfield/msvc-zero-width.slang
new file mode 100644
index 000000000..3363ef066
--- /dev/null
+++ b/tests/language-feature/bitfield/msvc-zero-width.slang
@@ -0,0 +1,30 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu -output-using-type -compile-arg -msvc-style-bitfield-packing
+
+// MSVC packing with zero-width bitfields
+// CHECK: 123
+// CHECK-NEXT: 4567
+// CHECK-NEXT: 1
+// CHECK-NEXT: 0
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct S {
+ int foo : 8; // First backing field
+ int breaker : 0; // Forces new backing field
+ int bar : 24; // Second backing field
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ S s;
+ s.foo = 123;
+ s.bar = 4567;
+ s.breaker = 9999; // Zero-width field, assignment has no effect
+ outputBuffer[0] = s.foo;
+ outputBuffer[1] = s.bar;
+ outputBuffer[2] = sizeof(S) == sizeof(int) * 2; // Two backing fields
+ outputBuffer[3] = s.breaker; // Always returns 0
+}
+
diff --git a/tests/language-feature/bitfield/repr-mixed.slang b/tests/language-feature/bitfield/repr-mixed.slang
new file mode 100644
index 000000000..44a3f69d9
--- /dev/null
+++ b/tests/language-feature/bitfield/repr-mixed.slang
@@ -0,0 +1,36 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu
+
+// Default packing keeps all fields in one backing field when they fit
+// struct MixedSizes { uint8_t a:4; uint8_t b:4; uint16_t c:8; uint16_t d:8; }
+// All packed in single uint32_t backing:
+// bits 0-3: a (0xA)
+// bits 4-7: b (0xB)
+// bits 8-15: c (0xCD)
+// bits 16-23: d (0xEF)
+// Expected: 0x00EFCDBA (top 8 bits unused)
+
+// CHECK: EFCDBA
+
+//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct MixedSizes {
+ uint8_t a : 4; // bits 0-3
+ uint8_t b : 4; // bits 4-7
+ uint16_t c : 8; // bits 8-15
+ uint16_t d : 8; // bits 16-23
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ MixedSizes m;
+ m.a = 0xA;
+ m.b = 0xB;
+ m.c = 0xCD;
+ m.d = 0xEF;
+
+ // With default packing, all fields are in one backing field
+ outputBuffer[0] = *((uint*)&m) & 0xFFFFFF; // Mask to 24 bits
+}
+
diff --git a/tests/language-feature/bitfield/repr.slang b/tests/language-feature/bitfield/repr.slang
new file mode 100644
index 000000000..a199b23ff
--- /dev/null
+++ b/tests/language-feature/bitfield/repr.slang
@@ -0,0 +1,36 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-cpu
+
+// Default GCC/Clang style packs from LSB to MSB
+// struct S { uint a:4; uint b:8; uint c:4; uint d:16; }
+// Memory layout (32-bit):
+// bits 0-3: a (0x5)
+// bits 4-11: b (0xAB)
+// bits 12-15: c (0xC)
+// bits 16-31: d (0xDEF0)
+// Expected: 0xDEF0CAB5
+
+// CHECK: DEF0CAB5
+
+//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<uint> outputBuffer;
+
+struct S {
+ uint a : 4; // bits 0-3
+ uint b : 8; // bits 4-11
+ uint c : 4; // bits 12-15
+ uint d : 16; // bits 16-31
+};
+
+[numthreads(1, 1, 1)]
+void computeMain()
+{
+ S s;
+ s.a = 0x5;
+ s.b = 0xAB;
+ s.c = 0xC;
+ s.d = 0xDEF0;
+
+ // Write the struct to memory and read it back as uint
+ outputBuffer[0] = *((uint*)&s);
+}
+