PageRenderTime 22ms CodeModel.GetById 5ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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}