Serializer.hx 12 KB

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