DirectXShaderCompiler icon indicating copy to clipboard operation
DirectXShaderCompiler copied to clipboard

[SPIR-V] Bitfield Members in Data Types

Open jaebaek opened this issue 4 years ago • 0 comments

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:

  1. For the continuous members Member0, Member1, .., MemberN with the same type Type
  • If the sum of bitfield sizes of Member0, Member1, .., MemberN is less than or equal to the size of Type in bits, it packs Member0, Member1, .., MemberN into a single Type.
  1. If a member has a type different from the previous member or the sum of bitfield sizes exceeds the size of Type in 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.

jaebaek avatar Dec 13 '21 21:12 jaebaek