Serializer.hx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. package hxsl;
  2. using hxsl.Ast;
  3. class Serializer {
  4. var out : haxe.io.BytesBuffer;
  5. var input : haxe.io.BytesInput;
  6. var varMap : Map<Int, TVar>;
  7. var idMap : Map<Int,Int>;
  8. var typeIdMap : Map<Type,Int>;
  9. var types : Array<Type>;
  10. var uid = 1;
  11. var tid = 1;
  12. public function new() {
  13. }
  14. inline function writeArr<T>( arr : Array<T>, f : T -> Void ) {
  15. writeVarInt(arr.length);
  16. for( v in arr ) f(v);
  17. }
  18. inline function readArr<T>( f : Void -> T ) {
  19. return [for( i in 0...readVarInt() ) f()];
  20. }
  21. function readVarInt() {
  22. var b = input.readByte();
  23. if( b < 128 )
  24. return b;
  25. if( b == 0xFF )
  26. return input.readInt32();
  27. return ((b & 0x7F) << 8) | input.readByte();
  28. }
  29. function writeVarInt( id : Int ) {
  30. if( id < 128 )
  31. out.addByte(id);
  32. else {
  33. var n = id >> 8;
  34. if( n >= 127 ) {
  35. out.addByte(0xFF);
  36. out.addInt32(n);
  37. } else {
  38. out.addByte(n | 128);
  39. out.addByte(id & 0xFF);
  40. }
  41. }
  42. }
  43. function writeID( id : Int ) {
  44. var id2 = idMap.get(id);
  45. if( id2 == null ) {
  46. id2 = uid++;
  47. idMap.set(id,id2);
  48. }
  49. writeVarInt(id2);
  50. }
  51. inline function readID() {
  52. return readVarInt();
  53. }
  54. function writeTID( t : Type ) {
  55. var tid = typeIdMap.get(t);
  56. if( tid != null ) {
  57. writeVarInt(tid);
  58. return false;
  59. }
  60. tid = this.tid++;
  61. typeIdMap.set(t,tid);
  62. writeVarInt(tid);
  63. return true;
  64. }
  65. function writeType( t : Type ) {
  66. out.addByte(t.getIndex());
  67. switch (t) {
  68. case TVec(size, t):
  69. out.addByte(size | (t.getIndex() << 3));
  70. case TBytes(size):
  71. out.addInt32(size);
  72. case TStruct(vl):
  73. if( writeTID(t) )
  74. writeArr(vl,writeVar);
  75. case TFun(variants):
  76. // not serialized
  77. case TArray(t, size), TBuffer(t, size):
  78. writeType(t);
  79. switch (size) {
  80. case SConst(v): out.addByte(0); writeVarInt(v);
  81. case SVar(v): writeVar(v);
  82. }
  83. case TChannel(size):
  84. out.addByte(size);
  85. case TVoid, TInt, TBool, TFloat, TString, TMat2, TMat3, TMat4, TMat3x4, TSampler2D, TSampler2DArray, TSamplerCube:
  86. }
  87. }
  88. static var TVECS = new Map();
  89. function readType() : Type {
  90. return switch( input.readByte() ) {
  91. case 0: TVoid;
  92. case 1: TInt;
  93. case 2: TBool;
  94. case 3: TFloat;
  95. case 4: TString;
  96. case 5:
  97. var bits = input.readByte();
  98. var v = TVECS.get(bits);
  99. if( v == null ) {
  100. v = TVec(bits & 7, VecType.createByIndex(bits>>3));
  101. TVECS.set(bits, v);
  102. }
  103. v;
  104. case 6: TMat3;
  105. case 7: TMat4;
  106. case 8: TMat3x4;
  107. case 9: TBytes(input.readInt32());
  108. case 10: TSampler2D;
  109. case 11: TSampler2DArray;
  110. case 12: TSamplerCube;
  111. case 13:
  112. var id = readVarInt();
  113. var t = types[id];
  114. if( t != null ) return t;
  115. t = TStruct(readArr(readVar));
  116. types[id] = t;
  117. t;
  118. case 14:
  119. TFun(null);
  120. case 15:
  121. var t = readType();
  122. var v = readVar();
  123. TArray(t, v == null ? SConst(readVarInt()) : SVar(v));
  124. case 16:
  125. var t = readType();
  126. var v = readVar();
  127. TBuffer(t, v == null ? SConst(readVarInt()) : SVar(v));
  128. case 17:
  129. TChannel(input.readByte());
  130. case 18: TMat2;
  131. default:
  132. throw "assert";
  133. }
  134. }
  135. function writeString( s : String ) {
  136. var bytes = haxe.io.Bytes.ofString(s);
  137. writeVarInt(bytes.length);
  138. out.add(bytes);
  139. }
  140. function readString() {
  141. var len = readVarInt();
  142. var s = input.read(len).getString(0,len);
  143. return s;
  144. }
  145. function writeVar( v : TVar ) {
  146. if( v == null ) {
  147. out.addByte(0);
  148. return;
  149. }
  150. writeID(v.id);
  151. if( varMap.exists(v.id) ) return;
  152. varMap.set(v.id, v);
  153. writeString(v.name);
  154. writeType(v.type);
  155. out.addByte(v.kind.getIndex());
  156. writeVar(v.parent);
  157. if( v.qualifiers == null )
  158. out.addByte(0);
  159. else {
  160. out.addByte(v.qualifiers.length);
  161. for( q in v.qualifiers ) {
  162. out.addByte(q.getIndex());
  163. switch (q) {
  164. case Private, Nullable, PerObject, Shared, Ignore:
  165. case Const(max): out.addInt32(max == null ? 0 : max);
  166. case Name(n): writeString(n);
  167. case Precision(p): out.addByte(p.getIndex());
  168. case Range(min, max): out.addDouble(min); out.addDouble(max);
  169. case PerInstance(v): out.addInt32(v);
  170. case Doc(s): writeString(s);
  171. }
  172. }
  173. }
  174. }
  175. function writeFun( f : TFunction ) {
  176. out.addByte(f.kind.getIndex());
  177. writeVar(f.ref);
  178. writeArr(f.args, writeVar);
  179. writeType(f.ret);
  180. writeExpr(f.expr);
  181. }
  182. function writeConst( c : Const ) {
  183. out.addByte(c.getIndex());
  184. switch (c) {
  185. case CNull:
  186. case CBool(b): out.addByte(b?1:0);
  187. case CInt(v): out.addInt32(v);
  188. case CFloat(v): out.addDouble(v);
  189. case CString(v): writeString(v);
  190. }
  191. }
  192. function writeExpr( e : TExpr ) {
  193. if( e == null ) {
  194. out.addByte(0);
  195. return;
  196. }
  197. out.addByte(e.e.getIndex() + 1);
  198. switch (e.e) {
  199. case TConst(c):
  200. writeConst(c);
  201. case TVar(v):
  202. writeVar(v);
  203. case TGlobal(g):
  204. out.addByte(g.getIndex());
  205. case TParenthesis(e):
  206. writeExpr(e);
  207. case TBlock(el):
  208. writeArr(el, writeExpr);
  209. case TBinop(op, e1, e2):
  210. switch( op ) {
  211. case OpAssignOp(op):
  212. out.addByte(op.getIndex() | 128);
  213. default:
  214. out.addByte(op.getIndex());
  215. }
  216. writeExpr(e1);
  217. writeExpr(e2);
  218. case TUnop(op, e1):
  219. out.addByte(op.getIndex());
  220. writeExpr(e1);
  221. case TVarDecl(v, init):
  222. writeVar(v);
  223. writeExpr(init);
  224. case TCall(e, args):
  225. writeExpr(e);
  226. writeArr(args, writeExpr);
  227. case TSwiz(e, regs):
  228. writeExpr(e);
  229. if( regs.length == 0 ) throw "assert";
  230. var bits = regs.length - 1, k = 2;
  231. for( r in regs ) {
  232. bits |= r.getIndex() << k;
  233. k += 2;
  234. }
  235. out.addByte(bits & 0xFF);
  236. out.addByte(bits >> 8);
  237. case TIf(econd, eif, eelse):
  238. writeExpr(econd);
  239. writeExpr(eif);
  240. writeExpr(eelse);
  241. case TDiscard:
  242. case TReturn(e):
  243. writeExpr(e);
  244. case TFor(v, it, loop):
  245. writeVar(v);
  246. writeExpr(it);
  247. writeExpr(loop);
  248. case TContinue:
  249. case TBreak:
  250. case TArray(e, index):
  251. writeExpr(e);
  252. writeExpr(index);
  253. case TArrayDecl(el):
  254. writeArr(el, writeExpr);
  255. case TSwitch(e, cases, def):
  256. writeExpr(e);
  257. writeArr(cases, function(c) {
  258. writeArr(c.values, writeExpr);
  259. writeExpr(c.expr);
  260. });
  261. writeExpr(def);
  262. case TWhile(e, loop, normalWhile):
  263. writeExpr(e);
  264. writeExpr(loop);
  265. out.addByte(normalWhile ? 1 : 0);
  266. case TMeta(m, args, e):
  267. writeString(m);
  268. writeArr(args, writeConst);
  269. writeExpr(e);
  270. }
  271. writeType(e.t);
  272. // no position
  273. }
  274. function readConst() : Const {
  275. return switch( input.readByte() ) {
  276. case 0: CNull;
  277. case 1: CBool(input.readByte() != 0);
  278. case 2: CInt(input.readInt32());
  279. case 3: CFloat(input.readDouble());
  280. case 4: CString(readString());
  281. default: throw "assert";
  282. }
  283. }
  284. static var BOPS = {
  285. var ops = Binop.createAll();
  286. ops.insert(OpAssignOp(null).getIndex(),null);
  287. ops;
  288. };
  289. static var UNOPS = Unop.createAll();
  290. static var TGLOBALS = hxsl.TGlobal.createAll();
  291. static var TSWIZ = new Map();
  292. static var REGS = [X,Y,Z,W];
  293. function readExpr() : TExpr {
  294. var k = input.readByte();
  295. if( k-- == 0 )
  296. return null;
  297. var e : TExprDef = switch( k ) {
  298. case 0: TConst(readConst());
  299. case 1: TVar(readVar());
  300. case 2: TGlobal(TGLOBALS[input.readByte()]);
  301. case 3: TParenthesis(readExpr());
  302. case 4: TBlock(readArr(readExpr));
  303. case 5:
  304. var op = input.readByte();
  305. TBinop(op >= 128 ? OpAssignOp(BOPS[op&127]) : BOPS[op], readExpr(), readExpr());
  306. case 6: TUnop(UNOPS[input.readByte()], readExpr());
  307. case 7: TVarDecl(readVar(), readExpr());
  308. case 8: TCall(readExpr(), readArr(readExpr));
  309. case 9:
  310. var e = readExpr();
  311. var bits = input.readUInt16();
  312. var swiz = TSWIZ.get(bits);
  313. if( swiz == null ) {
  314. swiz = [for( i in 0...(bits&3)+1 ) REGS[(bits>>(i*2+2))&3]];
  315. TSWIZ.set(bits, swiz);
  316. }
  317. TSwiz(e, swiz);
  318. case 10: TIf(readExpr(), readExpr(), readExpr());
  319. case 11: TDiscard;
  320. case 12: TReturn(readExpr());
  321. case 13: TFor(readVar(), readExpr(), readExpr());
  322. case 14: TContinue;
  323. case 15: TBreak;
  324. case 16: TArray(readExpr(), readExpr());
  325. case 17: TArrayDecl(readArr(readExpr));
  326. case 18: TSwitch(readExpr(), readArr(function() {
  327. return {
  328. values : readArr(readExpr),
  329. expr : readExpr(),
  330. };
  331. }), readExpr());
  332. case 19: TWhile(readExpr(), readExpr(), input.readByte() != 0);
  333. case 20: TMeta(readString(), readArr(readConst), readExpr());
  334. default: throw "assert";
  335. }
  336. return {
  337. e : e,
  338. t : readType(),
  339. p : null,
  340. }
  341. }
  342. static var VKINDS = VarKind.createAll();
  343. static var PRECS = Prec.createAll();
  344. function readVar() : TVar {
  345. var id = readID();
  346. if( id == 0 )
  347. return null;
  348. var v = varMap.get(id);
  349. if( v != null ) return v;
  350. v = {
  351. id : Tools.allocVarId(),
  352. name : readString(),
  353. type : null,
  354. kind : null,
  355. }
  356. varMap.set(id, v);
  357. v.type = readType();
  358. v.kind = VKINDS[input.readByte()];
  359. v.parent = readVar();
  360. var nq = input.readByte();
  361. if( nq > 0 ) {
  362. v.qualifiers = [];
  363. for( i in 0...nq ) {
  364. var qid = input.readByte();
  365. var q = switch( qid ) {
  366. case 0: var n = input.readInt32(); Const(n == 0 ? null : n);
  367. case 1: Private;
  368. case 2: Nullable;
  369. case 3: PerObject;
  370. case 4: Name(readString());
  371. case 5: Shared;
  372. case 6: Precision(PRECS[input.readByte()]);
  373. case 7: Range(input.readDouble(), input.readDouble());
  374. case 8: Ignore;
  375. case 9: PerInstance(input.readInt32());
  376. case 10: Doc(readString());
  377. default: throw "assert";
  378. }
  379. v.qualifiers.push(q);
  380. }
  381. }
  382. return v;
  383. }
  384. static var FKIND = FunctionKind.createAll();
  385. function readFun() : TFunction {
  386. return {
  387. kind : FKIND[input.readByte()],
  388. ref : readVar(),
  389. args : readArr(readVar),
  390. ret : readType(),
  391. expr : readExpr(),
  392. };
  393. }
  394. static var SIGN = 0x8B741D; // will be encoded to HXSL
  395. public function unserialize( data : String ) : ShaderData {
  396. input = new haxe.io.BytesInput(haxe.crypto.Base64.decode(data,false));
  397. if( input.readByte() != (SIGN & 0xFF) || input.readByte() != (SIGN >> 8) & 0xFF || input.readByte() != (SIGN >> 16) & 0xFF )
  398. throw "Invalid HXSL data";
  399. varMap = new Map();
  400. types = [];
  401. return {
  402. name : readString(),
  403. vars : readArr(readVar),
  404. funs : readArr(readFun),
  405. };
  406. }
  407. public function serialize( s : ShaderData ) {
  408. varMap = new Map();
  409. idMap = new Map();
  410. typeIdMap = new Map();
  411. out = new haxe.io.BytesBuffer();
  412. out.addByte(SIGN & 0xFF);
  413. out.addByte((SIGN >> 8) & 0xFF);
  414. out.addByte((SIGN >> 16) & 0xFF);
  415. writeString(s.name);
  416. writeArr(s.vars, writeVar);
  417. writeArr(s.funs, writeFun);
  418. return haxe.crypto.Base64.encode(out.getBytes(),false);
  419. }
  420. public static function run( s : ShaderData ) {
  421. return new Serializer().serialize(s);
  422. }
  423. }