8
8
import os
9
9
import tempfile
10
10
11
+ from dataclasses import dataclass
12
+ from typing import ClassVar
13
+
11
14
# pyre-ignore[21]: Could not find module `executorch.exir._serialize._bindings`.
12
15
import executorch .exir ._serialize ._bindings as bindings # @manual=//executorch/exir/_serialize:_bindings
13
16
@@ -32,3 +35,112 @@ def convert_to_flatbuffer(vk_graph: VkGraph) -> bytes:
32
35
output_path = os .path .join (d , "schema.bin" )
33
36
with open (output_path , "rb" ) as output_file :
34
37
return output_file .read ()
38
+
39
+
40
+ @dataclass
41
+ class VulkanDelegateHeader :
42
+ # Defines the byte region that each component of the header corresponds to
43
+ MAGIC_IX : ClassVar [slice ] = slice (4 , 8 )
44
+ HEADER_SIZE_IX : ClassVar [slice ] = slice (8 , 10 )
45
+ FLATBUFFER_OFFSET_IX : ClassVar [slice ] = slice (10 , 14 )
46
+ FLATBUFFER_SIZE_IX : ClassVar [slice ] = slice (14 , 18 )
47
+ CONSTANTS_OFFSET_IX : ClassVar [slice ] = slice (18 , 22 )
48
+ CONSTANTS_SIZE_IX : ClassVar [slice ] = slice (22 , 30 )
49
+ SHADERS_OFFSET_IX : ClassVar [slice ] = slice (30 , 34 )
50
+ SHADERS_SIZE_IX : ClassVar [slice ] = slice (34 , 42 )
51
+
52
+ # magic bytes that should be at the beginning of the header
53
+ EXPECTED_MAGIC : ClassVar [bytes ] = b"VKDG"
54
+ # The length of the header in bytes
55
+ EXPECTED_LENGTH : ClassVar [int ] = 42
56
+
57
+ # Instance attributes, @dataclass will turn these into constructor args
58
+ flatbuffer_offset : int
59
+ flatbuffer_size : int
60
+ constants_offset : int
61
+ constants_size : int
62
+ shaders_offset : int
63
+ shaders_size : int
64
+
65
+ @staticmethod
66
+ def from_bytes (data : bytes ) -> "VulkanDelegateHeader" :
67
+ if len (data ) > VulkanDelegateHeader .EXPECTED_LENGTH :
68
+ raise ValueError (
69
+ f"Expected header to be { VulkanDelegateHeader .EXPECTED_LENGTH } bytes, "
70
+ f"but got { len (data )} bytes."
71
+ )
72
+
73
+ magic_b : bytes = data [VulkanDelegateHeader .MAGIC_IX ]
74
+
75
+ if magic_b != VulkanDelegateHeader .EXPECTED_MAGIC :
76
+ raise ValueError (
77
+ f"Expected magic bytes to be { VulkanDelegateHeader .EXPECTED_MAGIC } , "
78
+ f"but got { magic_b } ."
79
+ )
80
+
81
+ length : int = int .from_bytes (
82
+ data [VulkanDelegateHeader .HEADER_SIZE_IX ], byteorder = "little"
83
+ )
84
+
85
+ if length != VulkanDelegateHeader .EXPECTED_LENGTH :
86
+ raise ValueError (
87
+ f"Expected header to be { VulkanDelegateHeader .EXPECTED_LENGTH } bytes, "
88
+ f"but got { length } bytes."
89
+ )
90
+
91
+ flatbuffer_offset_b : bytes = data [VulkanDelegateHeader .FLATBUFFER_OFFSET_IX ]
92
+ flatbuffer_size_b : bytes = data [VulkanDelegateHeader .FLATBUFFER_SIZE_IX ]
93
+ constants_offset_b : bytes = data [VulkanDelegateHeader .CONSTANTS_OFFSET_IX ]
94
+ constants_size_b : bytes = data [VulkanDelegateHeader .CONSTANTS_SIZE_IX ]
95
+ shaders_offset_b : bytes = data [VulkanDelegateHeader .SHADERS_OFFSET_IX ]
96
+ shaders_size_b : bytes = data [VulkanDelegateHeader .SHADERS_SIZE_IX ]
97
+
98
+ return VulkanDelegateHeader (
99
+ flatbuffer_offset = int .from_bytes (flatbuffer_offset_b , byteorder = "little" ),
100
+ flatbuffer_size = int .from_bytes (flatbuffer_size_b , byteorder = "little" ),
101
+ constants_offset = int .from_bytes (constants_offset_b , byteorder = "little" ),
102
+ constants_size = int .from_bytes (constants_size_b , byteorder = "little" ),
103
+ shaders_offset = int .from_bytes (shaders_offset_b , byteorder = "little" ),
104
+ shaders_size = int .from_bytes (shaders_size_b , byteorder = "little" ),
105
+ )
106
+
107
+ def is_valid (self ) -> bool :
108
+ if self .flatbuffer_size <= 0 :
109
+ return False
110
+
111
+ expected_offset = self .flatbuffer_offset + self .flatbuffer_size
112
+ if self .constants_offset < expected_offset :
113
+ return False
114
+
115
+ if self .constants_size <= 0 :
116
+ return False
117
+
118
+ expected_offset = self .constants_offset + self .constants_size
119
+ if self .shaders_offset < expected_offset :
120
+ return False
121
+
122
+ # shaders_size can be 0
123
+
124
+ return True
125
+
126
+ def to_bytes (self ) -> bytes :
127
+ if not self .is_valid ():
128
+ raise ValueError ("VulkanDelegateHeader instance contains invalid values" )
129
+
130
+ data : bytes = (
131
+ # 4 bytes of padding for magic bytes, this is so that the header magic
132
+ # bytes is in the same position as the flatbuffer header magic bytes
133
+ b"\x00 \x00 \x00 \x00 "
134
+ + self .EXPECTED_MAGIC
135
+ + self .EXPECTED_LENGTH .to_bytes (2 , byteorder = "little" )
136
+ + self .flatbuffer_offset .to_bytes (4 , byteorder = "little" )
137
+ + self .flatbuffer_size .to_bytes (4 , byteorder = "little" )
138
+ + self .constants_offset .to_bytes (4 , byteorder = "little" )
139
+ + self .constants_size .to_bytes (8 , byteorder = "little" )
140
+ + self .shaders_offset .to_bytes (4 , byteorder = "little" )
141
+ + self .shaders_size .to_bytes (8 , byteorder = "little" )
142
+ )
143
+
144
+ assert len (data ) == VulkanDelegateHeader .EXPECTED_LENGTH
145
+
146
+ return data
0 commit comments