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