shader_dx9bc.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. /*
  2. * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "bgfx_p.h"
  6. #include "shader_dx9bc.h"
  7. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-parameter");
  8. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunneeded-internal-declaration");
  9. namespace bgfx
  10. {
  11. struct Dx9bcOpcodeInfo
  12. {
  13. uint8_t numOperands;
  14. uint8_t numValues;
  15. };
  16. static const Dx9bcOpcodeInfo s_dx9bcOpcodeInfo[] =
  17. {
  18. { 0, 0 }, // NOP
  19. { 2, 0 }, // MOV
  20. { 3, 0 }, // ADD
  21. { 1, 0 }, // SUB
  22. { 4, 0 }, // MAD
  23. { 3, 0 }, // MUL
  24. { 2, 0 }, // RCP
  25. { 2, 0 }, // RSQ
  26. { 3, 0 }, // DP3
  27. { 3, 0 }, // DP4
  28. { 3, 0 }, // MIN
  29. { 3, 0 }, // MAX
  30. { 3, 0 }, // SLT
  31. { 3, 0 }, // SGE
  32. { 2, 0 }, // EXP
  33. { 2, 0 }, // LOG
  34. { 1, 0 }, // LIT
  35. { 1, 0 }, // DST
  36. { 4, 0 }, // LRP
  37. { 2, 0 }, // FRC
  38. { 1, 0 }, // M4X4
  39. { 1, 0 }, // M4X3
  40. { 1, 0 }, // M3X4
  41. { 1, 0 }, // M3X3
  42. { 1, 0 }, // M3X2
  43. { 0, 0 }, // CALL
  44. { 0, 0 }, // CALLNZ
  45. { 0, 0 }, // LOOP
  46. { 0, 0 }, // RET
  47. { 0, 0 }, // ENDLOOP
  48. { 0, 0 }, // LABEL
  49. { 1, 1 }, // DCL
  50. { 3, 0 }, // POW
  51. { 1, 0 }, // CRS
  52. { 1, 0 }, // SGN
  53. { 1, 0 }, // ABS
  54. { 2, 0 }, // NRM
  55. { 4, 0 }, // SINCOS
  56. { 1, 0 }, // REP
  57. { 0, 0 }, // ENDREP
  58. { 1, 0 }, // IF
  59. { 2, 0 }, // IFC
  60. { 0, 0 }, // ELSE
  61. { 0, 0 }, // ENDIF
  62. { 0, 0 }, // BREAK
  63. { 2, 0 }, // BREAKC
  64. { 2, 0 }, // MOVA
  65. { 1, 4 }, // DEFB
  66. { 1, 4 }, // DEFI
  67. { 0, 0 }, // 0
  68. { 0, 0 }, // 1
  69. { 0, 0 }, // 2
  70. { 0, 0 }, // 3
  71. { 0, 0 }, // 4
  72. { 0, 0 }, // 5
  73. { 0, 0 }, // 6
  74. { 0, 0 }, // 7
  75. { 0, 0 }, // 8
  76. { 0, 0 }, // 9
  77. { 0, 0 }, // 10
  78. { 0, 0 }, // 11
  79. { 0, 0 }, // 12
  80. { 0, 0 }, // 13
  81. { 0, 0 }, // 14
  82. { 1, 0 }, // TEXCOORD
  83. { 1, 0 }, // TEXKILL
  84. { 3, 0 }, // TEX
  85. { 1, 0 }, // TEXBEM
  86. { 1, 0 }, // TEXBEM1
  87. { 1, 0 }, // TEXREG2AR
  88. { 1, 0 }, // TEXREG2GB
  89. { 1, 0 }, // TEXM3X2PAD
  90. { 1, 0 }, // TEXM3X2TEX
  91. { 1, 0 }, // TEXM3X3PAD
  92. { 1, 0 }, // TEXM3X3TEX
  93. { 1, 0 }, // TEXM3X3DIFF
  94. { 1, 0 }, // TEXM3X3SPEC
  95. { 1, 0 }, // TEXM3X3VSPEC
  96. { 2, 0 }, // EXPP
  97. { 2, 0 }, // LOGP
  98. { 4, 0 }, // CND
  99. { 1, 4 }, // DEF
  100. { 1, 0 }, // TEXREG2RGB
  101. { 1, 0 }, // TEXDP3TEX
  102. { 1, 0 }, // TEXM3X2DEPTH
  103. { 1, 0 }, // TEXDP3
  104. { 1, 0 }, // TEXM3X3
  105. { 1, 0 }, // TEXDEPTH
  106. { 4, 0 }, // CMP
  107. { 1, 0 }, // BEM
  108. { 4, 0 }, // DP2ADD
  109. { 2, 0 }, // DSX
  110. { 2, 0 }, // DSY
  111. { 5, 0 }, // TEXLDD
  112. { 1, 0 }, // SETP
  113. { 3, 0 }, // TEXLDL
  114. { 0, 0 }, // BREAKP
  115. };
  116. BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcOpcodeInfo) == Dx9bcOpcode::Count);
  117. static const char* s_dx9bcOpcode[] =
  118. {
  119. "nop",
  120. "mov",
  121. "add",
  122. "sub",
  123. "mad",
  124. "mul",
  125. "rcp",
  126. "rsq",
  127. "dp3",
  128. "dp4",
  129. "min",
  130. "max",
  131. "slt",
  132. "sge",
  133. "exp",
  134. "log",
  135. "lit",
  136. "dst",
  137. "lrp",
  138. "frc",
  139. "m4x4",
  140. "m4x3",
  141. "m3x4",
  142. "m3x3",
  143. "m3x2",
  144. "call",
  145. "callnz",
  146. "loop",
  147. "ret",
  148. "endloop",
  149. "label",
  150. "dcl",
  151. "pow",
  152. "crs",
  153. "sgn",
  154. "abs",
  155. "nrm",
  156. "sincos",
  157. "rep",
  158. "endrep",
  159. "if",
  160. "ifc",
  161. "else",
  162. "endif",
  163. "break",
  164. "breakc",
  165. "mova",
  166. "defb",
  167. "defi",
  168. NULL,
  169. NULL,
  170. NULL,
  171. NULL,
  172. NULL,
  173. NULL,
  174. NULL,
  175. NULL,
  176. NULL,
  177. NULL,
  178. NULL,
  179. NULL,
  180. NULL,
  181. NULL,
  182. NULL,
  183. "texcoord",
  184. "texkill",
  185. "tex",
  186. "texbem",
  187. "texbem1",
  188. "texreg2ar",
  189. "texreg2gb",
  190. "texm3x2pad",
  191. "texm3x2tex",
  192. "texm3x3pad",
  193. "texm3x3tex",
  194. "texm3x3diff",
  195. "texm3x3spec",
  196. "texm3x3vspec",
  197. "expp",
  198. "logp",
  199. "cnd",
  200. "def",
  201. "texreg2rgb",
  202. "texdp3tex",
  203. "texm3x2depth",
  204. "texdp3",
  205. "texm3x3",
  206. "texdepth",
  207. "cmp",
  208. "bem",
  209. "dp2add",
  210. "dsx",
  211. "dsy",
  212. "texldd",
  213. "setp",
  214. "texldl",
  215. "breakp",
  216. };
  217. BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcOpcode) == Dx9bcOpcode::Count);
  218. const char* getName(Dx9bcOpcode::Enum _opcode)
  219. {
  220. BX_CHECK(_opcode < Dx9bcOpcode::Count, "Unknown opcode id %d (%x).", _opcode, _opcode);
  221. return s_dx9bcOpcode[_opcode];
  222. }
  223. static const char* s_dx9bcOperandType[] =
  224. {
  225. "r", // Temporary Register File
  226. "v", // Input Register File
  227. "c", // Constant Register File
  228. "t", // Texture Register File (PS)
  229. "oPos", // Rasterizer Register File
  230. "oD", // Attribute Output Register File
  231. "oT", // Texture Coordinate Output Register File
  232. "output", // Output register file for VS3.0+
  233. "i", // Constant Integer Vector Register File
  234. "oColor", // Color Output Register File
  235. "oDepth", // Depth Output Register File
  236. "s", // Sampler State Register File
  237. "c", // Constant Register File 2048 - 4095
  238. "c", // Constant Register File 4096 - 6143
  239. "c", // Constant Register File 6144 - 8191
  240. "b", // Constant Boolean register file
  241. "aL", // Loop counter register file
  242. "tempfloat16", // 16-bit float temp register file
  243. "misctype", // Miscellaneous (single) registers.
  244. "label", // Label
  245. "p", // Predicate register
  246. };
  247. BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcOperandType) == Dx9bcOperandType::Count);
  248. static const char* s_dx9bcDeclUsage[] =
  249. {
  250. "position",
  251. "blendweight",
  252. "blendindices",
  253. "normal",
  254. "psize",
  255. "texcoord",
  256. "tangent",
  257. "binormal",
  258. "tessfactor",
  259. "positiont",
  260. "color",
  261. "fog",
  262. "depth",
  263. "sample",
  264. };
  265. BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcDeclUsage) == Dx9bcDeclUsage::Count);
  266. int32_t read(bx::ReaderI* _reader, Dx9bcSubOperand& _subOperand, bx::Error* _err)
  267. {
  268. int32_t size = 0;
  269. uint32_t token;
  270. size += bx::read(_reader, token, _err);
  271. _subOperand.type = Dx9bcOperandType::Enum( ( (token & UINT32_C(0x70000000) ) >> 28)
  272. | ( (token & UINT32_C(0x00001800) ) >> 8) );
  273. _subOperand.regIndex = (token & UINT32_C(0x000007ff) );
  274. _subOperand.swizzleBits = uint8_t( (token & UINT32_C(0x00ff0000) ) >> 16);
  275. return size;
  276. }
  277. int32_t write(bx::WriterI* _writer, const Dx9bcSubOperand& _subOperand, bx::Error* _err)
  278. {
  279. int32_t size = 0;
  280. uint32_t token = 0;
  281. token |= (_subOperand.type << 28) & UINT32_C(0x70000000);
  282. token |= (_subOperand.type << 8) & UINT32_C(0x00001800);
  283. token |= _subOperand.regIndex & UINT32_C(0x000007ff);
  284. token |= (_subOperand.swizzleBits << 16) & UINT32_C(0x00ff0000);
  285. size += bx::write(_writer, token, _err);
  286. return size;
  287. }
  288. int32_t read(bx::ReaderI* _reader, Dx9bcOperand& _operand, bx::Error* _err)
  289. {
  290. int32_t size = 0;
  291. uint32_t token;
  292. size += bx::read(_reader, token, _err);
  293. _operand.type = Dx9bcOperandType::Enum( ( (token & UINT32_C(0x70000000) ) >> 28)
  294. | ( (token & UINT32_C(0x00001800) ) >> 8) );
  295. _operand.regIndex = (token & UINT32_C(0x000007ff) );
  296. _operand.addrMode = Dx9bcOperandAddrMode::Enum( (token & UINT32_C(0x00002000) ) >> 13);
  297. if (_operand.destination)
  298. {
  299. // Destination Parameter Token
  300. // https://msdn.microsoft.com/en-us/library/ff552738.aspx
  301. _operand.writeMask = uint8_t( (token & UINT32_C(0x000f0000) ) >> 16);
  302. _operand.saturate = 0 != (token & UINT32_C(0x00100000) );
  303. _operand.partialPrecision = 0 != (token & UINT32_C(0x00200000) );
  304. _operand.centroid = 0 != (token & UINT32_C(0x00400000) );
  305. }
  306. else
  307. {
  308. // Source Parameter Token
  309. // https://msdn.microsoft.com/en-us/library/ff569716%28v=vs.85%29.aspx
  310. _operand.writeMask = 0;
  311. _operand.saturate = false;
  312. _operand.partialPrecision = false;
  313. _operand.centroid = false;
  314. _operand.swizzleBits = uint8_t( (token & UINT32_C(0x00ff0000) ) >> 16);
  315. }
  316. if (Dx9bcOperandAddrMode::Relative == _operand.addrMode)
  317. {
  318. size += read(_reader, _operand.subOperand, _err);
  319. }
  320. return size;
  321. }
  322. int32_t write(bx::WriterI* _writer, const Dx9bcOperand& _operand, bx::Error* _err)
  323. {
  324. int32_t size = 0;
  325. uint32_t token = 0;
  326. token |= (_operand.type << 28) & UINT32_C(0x70000000);
  327. token |= (_operand.type << 8) & UINT32_C(0x00001800);
  328. token |= _operand.regIndex & UINT32_C(0x000007ff);
  329. token |= (_operand.addrMode << 13) & UINT32_C(0x00002000);
  330. size += bx::write(_writer, token, _err);
  331. if (Dx9bcOperandAddrMode::Relative == _operand.addrMode)
  332. {
  333. size += write(_writer, _operand.subOperand, _err);
  334. }
  335. return size;
  336. }
  337. int32_t read(bx::ReaderI* _reader, Dx9bcInstruction& _instruction, bx::Error* _err)
  338. {
  339. int32_t size = 0;
  340. uint32_t token;
  341. size += bx::read(_reader, token, _err);
  342. _instruction.opcode = Dx9bcOpcode::Enum( (token & UINT32_C(0x0000ffff) ) );
  343. if (Dx9bcOpcode::Comment == _instruction.opcode)
  344. {
  345. _instruction.specific = 0;
  346. _instruction.length = uint16_t( (token & UINT32_C(0x7fff0000) ) >> 16) + 1;
  347. _instruction.predicated = false;
  348. _instruction.coissue = false;
  349. }
  350. else
  351. {
  352. _instruction.specific = uint8_t( (token & UINT32_C(0x00ff0000) ) >> 16);
  353. _instruction.length = uint8_t( (token & UINT32_C(0x0f000000) ) >> 24) + 1;
  354. _instruction.predicated = 0 != (token & UINT32_C(0x10000000) );
  355. _instruction.coissue = 0 != (token & UINT32_C(0x40000000) );
  356. }
  357. if (Dx9bcOpcode::Count <= _instruction.opcode)
  358. {
  359. if (Dx9bcOpcode::Comment == _instruction.opcode)
  360. {
  361. for (int32_t ii = 0, num = _instruction.length-1; ii < num; ++ii)
  362. {
  363. uint32_t tmp;
  364. size += bx::read(_reader, tmp, _err);
  365. }
  366. }
  367. return size;
  368. }
  369. uint32_t currOp = 0;
  370. const Dx9bcOpcodeInfo& info = s_dx9bcOpcodeInfo[bx::uint32_min(_instruction.opcode, Dx9bcOpcode::Count)];
  371. _instruction.numOperands = info.numOperands;
  372. _instruction.numValues = info.numValues;
  373. switch (_instruction.opcode)
  374. {
  375. case Dx9bcOpcode::SINCOS:
  376. if (5 > _instruction.length)
  377. {
  378. _instruction.numOperands = 2;
  379. }
  380. break;
  381. default:
  382. break;
  383. };
  384. //BX_TRACE("%d (%d), %d, %d, 0x%08x"
  385. // , _instruction.opcode
  386. // , bx::uint32_min(_instruction.opcode, Dx9bcOpcode::Count)
  387. // , _instruction.length
  388. // , _instruction.numOperands
  389. // , token
  390. // );
  391. const bool valuesBeforeOpcode = false
  392. || Dx9bcOpcode::DCL == _instruction.opcode
  393. ;
  394. if (valuesBeforeOpcode
  395. && 0 < info.numValues)
  396. {
  397. size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t), _err);
  398. }
  399. _instruction.operand[0].destination = true;
  400. switch (_instruction.numOperands)
  401. {
  402. case 6: size += read(_reader, _instruction.operand[currOp++], _err);
  403. case 5: size += read(_reader, _instruction.operand[currOp++], _err);
  404. case 4: size += read(_reader, _instruction.operand[currOp++], _err);
  405. case 3: size += read(_reader, _instruction.operand[currOp++], _err);
  406. case 2: size += read(_reader, _instruction.operand[currOp++], _err);
  407. case 1: size += read(_reader, _instruction.operand[currOp++], _err);
  408. case 0:
  409. if (!valuesBeforeOpcode
  410. && 0 < info.numValues)
  411. {
  412. size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t), _err);
  413. }
  414. break;
  415. default:
  416. BX_CHECK(false, "Instruction %s with invalid number of operands %d (numValues %d)."
  417. , getName(_instruction.opcode)
  418. , _instruction.numOperands
  419. , info.numValues
  420. );
  421. break;
  422. }
  423. return size;
  424. }
  425. int32_t write(bx::WriterI* _writer, const Dx9bcInstruction& _instruction, bx::Error* _err)
  426. {
  427. int32_t size = 0;
  428. uint32_t token = 0;
  429. token |= _instruction.opcode & UINT32_C(0x0000ffff);
  430. token |= (_instruction.specific << 16) & UINT32_C(0x00ff0000);
  431. token |= ( (_instruction.length - 1) << 24) & UINT32_C(0x0f000000);
  432. size += bx::write(_writer, token, _err);
  433. uint32_t currOp = 0;
  434. switch (_instruction.numOperands)
  435. {
  436. case 6: size += write(_writer, _instruction.operand[currOp++], _err);
  437. case 5: size += write(_writer, _instruction.operand[currOp++], _err);
  438. case 4: size += write(_writer, _instruction.operand[currOp++], _err);
  439. case 3: size += write(_writer, _instruction.operand[currOp++], _err);
  440. case 2: size += write(_writer, _instruction.operand[currOp++], _err);
  441. case 1: size += write(_writer, _instruction.operand[currOp++], _err);
  442. case 0:
  443. break;
  444. }
  445. return 0;
  446. }
  447. int32_t toString(char* _out, int32_t _size, const Dx9bcInstruction& _instruction)
  448. {
  449. int32_t size = 0;
  450. if (Dx9bcOpcode::Comment == _instruction.opcode
  451. || Dx9bcOpcode::Phase == _instruction.opcode)
  452. {
  453. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  454. , "// %x"
  455. , _instruction.opcode
  456. );
  457. return size;
  458. }
  459. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  460. , "%2d %s"
  461. , _instruction.opcode
  462. , getName(_instruction.opcode)
  463. );
  464. switch (_instruction.opcode)
  465. {
  466. case Dx9bcOpcode::DCL:
  467. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  468. , "_%s%d (%d, %d, %d, %d)"
  469. , s_dx9bcDeclUsage[_instruction.value[0] & UINT32_C(0x0000000f)]
  470. , (_instruction.value[0] & UINT32_C(0x000f0000) )>>16
  471. , (_instruction.value[0] & UINT32_C(0x08000000) )>>27 // ?
  472. , (_instruction.value[0] & UINT32_C(0x10000000) )>>28 // texture2d
  473. , (_instruction.value[0] & UINT32_C(0x20000000) )>>29 // textureCube
  474. , (_instruction.value[0] & UINT32_C(0x40000000) )>>30 // texture3d
  475. );
  476. break;
  477. default:
  478. break;
  479. }
  480. for (uint32_t ii = 0; ii < _instruction.numOperands; ++ii)
  481. {
  482. const Dx9bcOperand& operand = _instruction.operand[ii];
  483. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  484. , "%s%s%d"
  485. , 0 == ii ? " " : ", "
  486. , s_dx9bcOperandType[operand.type]
  487. , operand.regIndex
  488. );
  489. if (operand.destination)
  490. {
  491. if (0xf > operand.writeMask
  492. && 0 < operand.writeMask)
  493. {
  494. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  495. , ".%s%s%s%s"
  496. , 0 == (operand.writeMask & 1) ? "" : "x"
  497. , 0 == (operand.writeMask & 2) ? "" : "y"
  498. , 0 == (operand.writeMask & 4) ? "" : "z"
  499. , 0 == (operand.writeMask & 8) ? "" : "w"
  500. );
  501. }
  502. }
  503. else
  504. {
  505. if (Dx9bcOperandAddrMode::Relative == operand.addrMode)
  506. {
  507. const bool array = true;
  508. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  509. , "["
  510. );
  511. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  512. , "%s%d"
  513. , s_dx9bcOperandType[operand.subOperand.type]
  514. , operand.subOperand.regIndex
  515. );
  516. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  517. , "%s"
  518. , array ? "]" : ""
  519. );
  520. }
  521. if (0xe4 != operand.swizzleBits)
  522. {
  523. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  524. , ".%c%c%c%c"
  525. , "xyzw"[(operand.swizzleBits )&0x3]
  526. , "xyzw"[(operand.swizzleBits>>2)&0x3]
  527. , "xyzw"[(operand.swizzleBits>>4)&0x3]
  528. , "xyzw"[(operand.swizzleBits>>6)&0x3]
  529. );
  530. }
  531. }
  532. }
  533. switch (_instruction.opcode)
  534. {
  535. case Dx9bcOpcode::DEF:
  536. for (uint32_t jj = 0; jj < _instruction.numValues; ++jj)
  537. {
  538. union { int32_t i; float f; } cast = { _instruction.value[jj] };
  539. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  540. , "%s%f%s"
  541. , 0 == jj ? " (" : ", "
  542. , cast.f
  543. , uint32_t(_instruction.numValues-1) == jj ? ")" : ""
  544. );
  545. }
  546. break;
  547. case Dx9bcOpcode::DEFI:
  548. for (uint32_t jj = 0; jj < _instruction.numValues; ++jj)
  549. {
  550. size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
  551. , "%s%d%s"
  552. , 0 == jj ? " (" : ", "
  553. , _instruction.value[jj]
  554. , uint32_t(_instruction.numValues-1) == jj ? ")" : ""
  555. );
  556. }
  557. break;
  558. default:
  559. break;
  560. }
  561. return size;
  562. }
  563. int32_t read(bx::ReaderSeekerI* _reader, Dx9bcShader& _shader, bx::Error* _err)
  564. {
  565. int32_t size = 0;
  566. int64_t offset = bx::seek(_reader);
  567. for (;;)
  568. {
  569. Dx9bcInstruction instruction;
  570. int32_t length = read(_reader, instruction, _err);
  571. size += length;
  572. if (Dx9bcOpcode::Count > instruction.opcode)
  573. {
  574. char temp[512];
  575. toString(temp, 512, instruction);
  576. BX_CHECK(length/4 == instruction.length
  577. , "%s\nread %d, expected %d"
  578. , temp
  579. , length/4
  580. , instruction.length
  581. );
  582. }
  583. else
  584. {
  585. if (Dx9bcOpcode::End == instruction.opcode)
  586. {
  587. size -= length;
  588. break;
  589. }
  590. }
  591. }
  592. bx::seek(_reader, offset, bx::Whence::Begin);
  593. _shader.byteCode.resize(size);
  594. bx::read(_reader, _shader.byteCode.data(), size, _err);
  595. return size;
  596. }
  597. int32_t write(bx::WriterI* _writer, const Dx9bcShader& _shader, bx::Error* _err)
  598. {
  599. BX_UNUSED(_writer, _shader, _err);
  600. return 0;
  601. }
  602. int32_t read(bx::ReaderSeekerI* _reader, Dx9bc& _bc, bx::Error* _err)
  603. {
  604. int32_t size = 0;
  605. size += bx::read(_reader, _bc.version, _err);
  606. bool pixelShader = (0xffff0000 == (_bc.version & 0xffff0000) );
  607. uint32_t versionMajor = (_bc.version>>8)&0xff;
  608. uint32_t versionMinor = _bc.version&0xff;
  609. BX_UNUSED(pixelShader, versionMajor, versionMinor);
  610. BX_TRACE("%s shader %d.%d"
  611. , pixelShader ? "pixel" : "vertex"
  612. , versionMajor
  613. , versionMinor
  614. );
  615. size += read(_reader, _bc.shader, _err);
  616. return size;
  617. }
  618. int32_t write(bx::WriterSeekerI* _writer, const Dx9bc& _dxbc, bx::Error* _err)
  619. {
  620. BX_UNUSED(_writer, _dxbc, _err);
  621. return 0;
  622. }
  623. void parse(const Dx9bcShader& _src, Dx9bcParseFn _fn, void* _userData, bx::Error* _err)
  624. {
  625. BX_ERROR_SCOPE(_err);
  626. bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) );
  627. bx::Error err;
  628. for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;)
  629. {
  630. Dx9bcInstruction instruction;
  631. uint32_t size = read(&reader, instruction, _err);
  632. BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size);
  633. bool cont = _fn(token * sizeof(uint32_t), instruction, _userData);
  634. if (!cont)
  635. {
  636. return;
  637. }
  638. token += instruction.length;
  639. }
  640. }
  641. void filter(Dx9bcShader& _dst, const Dx9bcShader& _src, Dx9bcFilterFn _fn, void* _userData, bx::Error* _err)
  642. {
  643. BX_ERROR_SCOPE(_err);
  644. bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) );
  645. bx::MemoryBlock mb(g_allocator);
  646. bx::MemoryWriter writer(&mb);
  647. for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;)
  648. {
  649. Dx9bcInstruction instruction;
  650. uint32_t size = read(&reader, instruction, _err);
  651. BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size);
  652. _fn(instruction, _userData);
  653. write(&writer, instruction, _err);
  654. token += instruction.length;
  655. }
  656. uint8_t* data = (uint8_t*)mb.more();
  657. uint32_t size = uint32_t(bx::getSize(&writer) );
  658. _dst.byteCode.reserve(size);
  659. memcpy(_dst.byteCode.data(), data, size);
  660. }
  661. } // namespace bgfx