DirectXShaderCompiler
DirectXShaderCompiler copied to clipboard
[SPIR-V] Bitfield Members in Data Types
SPIR-V code gen has to support bitfield members for HLSL 2021. We must decide the type and memory layout for members with bitfields. Based on experiments with the DXIL code gen,
// HLSL
struct foo {
int x : 8;
int : 8;
int y : 16;
};
// DXIL
%struct.foo = type { i32 }
// load foo.y
%y = getelementptr inbounds %struct.foo, %struct.foo* %p, i32 0, i32 0, !dbg !36 ; line:18 col:33
%bf.load = load i32, i32* %y, align 4, !dbg !36 ; line:18 col:33
%bf.ashr = ashr i32 %bf.load, 16, !dbg !36 ; line:18 col:33
// load foo.x
%x1 = getelementptr inbounds %struct.foo, %struct.foo* %p, i32 0, i32 0, !dbg !41 ; line:18 col:21
%bf.load2 = load i32, i32* %x1, align 4, !dbg !41 ; line:18 col:21
%bf.shl = shl i32 %bf.load2, 24, !dbg !41 ; line:18 col:21
%bf.ashr3 = ashr i32 %bf.shl, 24, !dbg !41 ; line:18 col:21
// HLSL
struct foo {
int x : 8;
int : 15;
int y : 16;
};
// DXIL
%struct.foo = type { i32, i32 }
// load foo.y
%y = getelementptr inbounds %struct.foo, %struct.foo* %p, i32 0, i32 1, !dbg !37 ; line:18 col:33
%bf.load = load i32, i32* %y, align 4, !dbg !37 ; line:18 col:33
%bf.shl = shl i32 %bf.load, 16, !dbg !37 ; line:18 col:33
%bf.ashr = ashr i32 %bf.shl, 16, !dbg !37 ; line:18 col:33
// load foo.x
%x1 = getelementptr inbounds %struct.foo, %struct.foo* %p, i32 0, i32 0, !dbg !42 ; line:18 col:21
%bf.load2 = load i32, i32* %x1, align 4, !dbg !42 ; line:18 col:21
%bf.shl3 = shl i32 %bf.load2, 24, !dbg !42 ; line:18 col:21
%bf.ashr4 = ashr i32 %bf.shl3, 24, !dbg !42 ; line:18 col:21
// HLSL
struct foo {
int x : 8;
min16int : 16;
int y : 16;
};
// DXIL
%struct.foo = type { i32, i16, i32 }
// load foo.y
%y = getelementptr inbounds %struct.foo, %struct.foo* %p, i32 0, i32 2, !dbg !38 ; line:18 col:33
%bf.load = load i32, i32* %y, align 4, !dbg !38 ; line:18 col:33
%bf.shl = shl i32 %bf.load, 16, !dbg !38 ; line:18 col:33
%bf.ashr = ashr i32 %bf.shl, 16, !dbg !38 ; line:18 col:33
// load foo.x
%x1 = getelementptr inbounds %struct.foo, %struct.foo* %p, i32 0, i32 0, !dbg !43 ; line:18 col:21
%bf.load2 = load i32, i32* %x1, align 4, !dbg !43 ; line:18 col:21
%bf.shl3 = shl i32 %bf.load2, 24, !dbg !43 ; line:18 col:21
%bf.ashr4 = ashr i32 %bf.shl3, 24, !dbg !43 ; line:18 col:21
I guess the rules of types and memory layout for bitfield members in DXIL code gen:
- For the continuous members
Member0,Member1, ..,MemberNwith the same typeType
- If the sum of bitfield sizes of
Member0,Member1, ..,MemberNis less than or equal to the size ofTypein bits, it packsMember0,Member1, ..,MemberNinto a singleType.
- If a member has a type different from the previous member or the sum of bitfield sizes exceeds the size of
Typein bits, it packs the members starting from the next member.
The DXIL code gen uses shl and ashr to extract the bitfield. We can use OpShiftRightArithmetic and OpShiftLeftLogical for SPIR-V code gen.