/src/aerys/minko/render/shader/compiler/graph/nodes/vertex/Instruction.as

https://bitbucket.org/HopeSky/mars_nd2d · ActionScript · 257 lines · 211 code · 40 blank · 6 comment · 29 complexity · 8862d2b914d5f71c95579601b1433cae MD5 · raw file

  1. package aerys.minko.render.shader.compiler.graph.nodes.vertex
  2. {
  3. import aerys.minko.render.shader.compiler.CRC32;
  4. import aerys.minko.render.shader.compiler.InstructionFlag;
  5. import aerys.minko.render.shader.compiler.graph.nodes.AbstractNode;
  6. import aerys.minko.render.shader.compiler.register.Components;
  7. import flash.utils.Dictionary;
  8. /**
  9. * @private
  10. * @author Romain Gilliotte
  11. */
  12. public class Instruction extends AbstractNode
  13. {
  14. public static const MOV : uint = 0x00;
  15. public static const ADD : uint = 0x01;
  16. public static const SUB : uint = 0x02;
  17. public static const MUL : uint = 0x03;
  18. public static const DIV : uint = 0x04;
  19. public static const RCP : uint = 0x05;
  20. public static const MIN : uint = 0x06;
  21. public static const MAX : uint = 0x07;
  22. public static const FRC : uint = 0x08;
  23. public static const SQT : uint = 0x09;
  24. public static const RSQ : uint = 0x0a;
  25. public static const POW : uint = 0x0b;
  26. public static const LOG : uint = 0x0c;
  27. public static const EXP : uint = 0x0d;
  28. public static const NRM : uint = 0x0e;
  29. public static const SIN : uint = 0x0f;
  30. public static const COS : uint = 0x10;
  31. public static const CRS : uint = 0x11;
  32. public static const DP3 : uint = 0x12;
  33. public static const DP4 : uint = 0x13;
  34. public static const ABS : uint = 0x14;
  35. public static const NEG : uint = 0x15;
  36. public static const SAT : uint = 0x16;
  37. public static const M33 : uint = 0x17;
  38. public static const M44 : uint = 0x18;
  39. public static const M34 : uint = 0x19;
  40. public static const KIL : uint = 0x27;
  41. public static const TEX : uint = 0x28;
  42. public static const SGE : uint = 0x29;
  43. public static const SLT : uint = 0x2a;
  44. public static const SEQ : uint = 0x2c;
  45. public static const SNE : uint = 0x2d;
  46. public static const MUL_MAT33 : uint = 0x100;
  47. public static const MUL_MAT44 : uint = 0x101;
  48. public static const NAME : Dictionary = new Dictionary();
  49. {
  50. NAME[MOV] = 'mov'; NAME[ADD] = 'add'; NAME[SUB] = 'sub';
  51. NAME[MUL] = 'mul'; NAME[DIV] = 'div'; NAME[RCP] = 'rcp';
  52. NAME[MIN] = 'min'; NAME[MAX] = 'max'; NAME[FRC] = 'frc';
  53. NAME[SQT] = 'sqt'; NAME[RSQ] = 'rsq'; NAME[POW] = 'pow';
  54. NAME[LOG] = 'log'; NAME[EXP] = 'exp'; NAME[NRM] = 'nrm';
  55. NAME[SIN] = 'sin'; NAME[COS] = 'cos'; NAME[CRS] = 'crs';
  56. NAME[DP3] = 'dp3'; NAME[DP4] = 'dp4'; NAME[ABS] = 'abs';
  57. NAME[NEG] = 'neg'; NAME[SAT] = 'sat'; NAME[M33] = 'm33';
  58. NAME[M44] = 'm44'; NAME[M34] = 'm34'; NAME[TEX] = 'tex';
  59. NAME[KIL] = 'kil'; NAME[SGE] = 'sge'; NAME[SLT] = 'slt';
  60. NAME[SEQ] = 'seq'; NAME[SNE] = 'sne';
  61. NAME[MUL_MAT33] = 'mulMat33';
  62. NAME[MUL_MAT44] = 'mulMat44';
  63. }
  64. private static const FLAGS : Dictionary = new Dictionary();
  65. {
  66. FLAGS[MOV] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE | InstructionFlag.LINEAR;
  67. FLAGS[ADD] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.COMMUTATIVE | InstructionFlag.LINEAR;
  68. FLAGS[SUB] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.LINEAR;
  69. FLAGS[MUL] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.COMMUTATIVE | InstructionFlag.LINEAR;
  70. FLAGS[DIV] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.LINEAR;
  71. FLAGS[RCP] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE | InstructionFlag.LINEAR;
  72. FLAGS[MIN] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.COMMUTATIVE;
  73. FLAGS[MAX] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.COMMUTATIVE;
  74. FLAGS[FRC] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  75. FLAGS[SQT] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  76. FLAGS[RSQ] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  77. FLAGS[POW] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE;
  78. FLAGS[LOG] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  79. FLAGS[EXP] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  80. FLAGS[NRM] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.SINGLE;
  81. FLAGS[SIN] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  82. FLAGS[COS] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  83. FLAGS[CRS] = InstructionFlag.AVAILABLE_ALL;
  84. FLAGS[DP3] = InstructionFlag.AVAILABLE_ALL;
  85. FLAGS[DP4] = InstructionFlag.AVAILABLE_ALL;
  86. FLAGS[ABS] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  87. FLAGS[NEG] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE | InstructionFlag.LINEAR;
  88. FLAGS[SAT] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.SINGLE;
  89. FLAGS[M33] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.SPECIAL_MATRIX | InstructionFlag.LINEAR;
  90. FLAGS[M44] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.SPECIAL_MATRIX | InstructionFlag.LINEAR;
  91. FLAGS[M34] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.SPECIAL_MATRIX | InstructionFlag.LINEAR;
  92. FLAGS[KIL] = InstructionFlag.AVAILABLE_FS | InstructionFlag.SINGLE;
  93. FLAGS[TEX] = InstructionFlag.AVAILABLE_FS;
  94. FLAGS[SGE] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE;
  95. FLAGS[SLT] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE;
  96. FLAGS[SEQ] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.COMMUTATIVE;
  97. FLAGS[SNE] = InstructionFlag.AVAILABLE_ALL | InstructionFlag.COMPONENT_WISE | InstructionFlag.COMMUTATIVE;
  98. FLAGS[MUL_MAT33] = InstructionFlag.AVAILABLE_CPU | InstructionFlag.ASSOCIATIVE;
  99. FLAGS[MUL_MAT44] = InstructionFlag.AVAILABLE_CPU | InstructionFlag.ASSOCIATIVE;
  100. }
  101. private var _id : uint;
  102. public function get id() : uint { return _id; }
  103. public function get name() : String { return NAME[_id]; }
  104. public function get argument1() : AbstractNode { return getArgumentAt(0); }
  105. public function get argument2() : AbstractNode { return getArgumentAt(1); }
  106. public function get component1() : uint { return getComponentAt(0); }
  107. public function get component2() : uint { return getComponentAt(1); }
  108. public function set argument1(v : AbstractNode) : void { setArgumentAt(0, v); }
  109. public function set argument2(v : AbstractNode) : void { setArgumentAt(1, v); }
  110. public function set component1(v : uint) : void { setComponentAt(0, v); }
  111. public function set component2(v : uint) : void { setComponentAt(1, v); }
  112. public function get isAssociative() : Boolean
  113. {
  114. return (FLAGS[_id] & InstructionFlag.ASSOCIATIVE) != 0;
  115. }
  116. public function get isComponentWise() : Boolean
  117. {
  118. return (FLAGS[_id] & InstructionFlag.COMPONENT_WISE) != 0;
  119. }
  120. public function get isSingle() : Boolean
  121. {
  122. return (FLAGS[_id] & InstructionFlag.SINGLE) != 0;
  123. }
  124. public function get isLinear() : Boolean
  125. {
  126. return (FLAGS[_id] & InstructionFlag.LINEAR) != 0;
  127. }
  128. public function isCommutative() : Boolean
  129. {
  130. return (FLAGS[_id] & InstructionFlag.COMMUTATIVE) != 0;
  131. }
  132. public function Instruction(id : uint,
  133. argument1 : AbstractNode,
  134. argument2 : AbstractNode = null)
  135. {
  136. _id = id;
  137. var component1 : uint = id == MUL_MAT33 || id == MUL_MAT44 ?
  138. Components.createContinuous(0, 0, 4, 4) :
  139. Components.createContinuous(0, 0, argument1.size, argument1.size)
  140. var arguments : Vector.<AbstractNode> = new <AbstractNode>[argument1];
  141. var components : Vector.<uint> = new <uint>[component1];
  142. if (!isSingle)
  143. {
  144. var component2 : uint;
  145. if ((FLAGS[id] & InstructionFlag.SPECIAL_MATRIX) != 0)
  146. component2 = Components.createContinuous(0, 0, 4, 4);
  147. else if (id != TEX && id != MUL_MAT33 && id != MUL_MAT44)
  148. component2 = Components.createContinuous(0, 0, argument2.size, argument2.size);
  149. arguments.push(argument2);
  150. components.push(component2);
  151. }
  152. arguments.fixed = components.fixed = true;
  153. super(arguments, components);
  154. }
  155. override protected function computeHash() : uint
  156. {
  157. // commutative operations invert the arguments when computing the hash if arg1.crc > arg2.crc
  158. // that way, mul(a, b).hash == mul(b, a).hash
  159. var hashLeft : String = argument1.hash.toString(16) + '_' + component1.toString(16);
  160. if ((FLAGS[_id] & InstructionFlag.SINGLE) != 0)
  161. return CRC32.computeForString(hashLeft);
  162. else
  163. {
  164. var hashRight : String = argument2.hash.toString(16) + '_' + component2.toString(16);
  165. if ((FLAGS[_id] & InstructionFlag.COMMUTATIVE) != 0 && argument1.hash > argument2.hash)
  166. return CRC32.computeForString(hashRight + hashLeft);
  167. else
  168. return CRC32.computeForString(hashLeft + hashRight);
  169. }
  170. }
  171. override protected function computeSize() : uint
  172. {
  173. switch (_id)
  174. {
  175. case DP3: case DP4: return 1;
  176. case M33: case M34: case NRM: case CRS: return 3;
  177. case TEX: case M44: return 4;
  178. default:
  179. var nodeSize : uint;
  180. nodeSize = Components.getMaxWriteOffset(component1)
  181. - Components.getMinWriteOffset(component1) + 1;
  182. if (nodeSize > 4)
  183. throw new Error();
  184. if (!isSingle)
  185. nodeSize = Math.max(nodeSize,
  186. Components.getMaxWriteOffset(component2)
  187. - Components.getMinWriteOffset(component2) + 1
  188. );
  189. if (nodeSize < 1)
  190. throw new Error();
  191. if (nodeSize > 4)
  192. throw new Error();
  193. return nodeSize;
  194. }
  195. }
  196. override public function toString() : String
  197. {
  198. return name;
  199. }
  200. override public function clone() : AbstractNode
  201. {
  202. var clone : Instruction;
  203. if (isSingle)
  204. {
  205. clone = new Instruction(_id, argument1);
  206. clone.component1 = component1;
  207. }
  208. else
  209. {
  210. clone = new Instruction(_id, argument1, argument2);
  211. clone.component1 = component1;
  212. clone.component2 = component2;
  213. }
  214. return clone;
  215. }
  216. }
  217. }