Parcourir la source

added Fract, force reading of unused inputs

Nicolas Cannasse il y a 11 ans
Parent
commit
ab69425492
2 fichiers modifiés avec 38 ajouts et 3 suppressions
  1. 18 2
      hxsl/AgalOptim.hx
  2. 20 1
      hxsl/AgalOut.hx

+ 18 - 2
hxsl/AgalOptim.hx

@@ -41,6 +41,9 @@ class AgalOptim {
 		data = d;
 		code = d.code.copy();
 
+		var inputs = [];
+		for( op in code ) iter(op, function(r,_) if( r.t == RAttr ) inputs[r.index] = true);
+
 		while( true ) {
 			changed = false;
 			buildLive(true);
@@ -53,6 +56,14 @@ class AgalOptim {
 			break;
 		}
 
+		// added unread inputs
+		for( op in code ) iter(op, function(r, _) if( r.t == RAttr ) inputs[r.index] = false);
+		for( i in 0...inputs.length )
+			if( inputs[i] ) {
+				changed = true;
+				code.push(OMov(allocTemp(4), { t : RAttr, index : i, swiz : null, access : null } ));
+			}
+
 		unoptim();
 		if( changed )
 			buildLive(false);
@@ -212,6 +223,12 @@ class AgalOptim {
 		}
 	}
 
+	function allocTemp( size : Int ) : Reg {
+		var r = { t : RTemp, index : regs.length, swiz : size == 4 ? null : [for( i in 0...size ) COMPS[i]], access : null };
+		regs.push(null);
+		return r;
+	}
+
 	function unoptim() {
 		// expand invalid AGAL opcodes with additional MOV
 		var out = [];
@@ -221,8 +238,7 @@ class AgalOptim {
 			if( args.length > 2 )
 				switch( [args[1].t, args[2].t] ) {
 				case [RConst, RConst]:
-					var r = { t : RTemp, index : regs.length, swiz : [for( i in 0...swiz(args[1]).length ) COMPS[i]], access : null };
-					regs.push(null);
+					var r = allocTemp(swiz(args[1]).length);
 					out.push(OMov(r, args[1]));
 					out.push(Opcode.createByIndex(op.getIndex(), [args[0], r, args[2]]));
 					changed = true;

+ 20 - 1
hxsl/AgalOut.hx

@@ -15,6 +15,7 @@ class AgalOut {
 	var varMap : Map<Int, Reg>;
 	var tmpCount : Int;
 	var nullReg : Reg;
+	var unused : Map<Int, Reg>;
 
 	public function new() {
 	}
@@ -30,6 +31,7 @@ class AgalOut {
 		opcodes = [];
 		tmpCount = 0;
 		varMap = new Map();
+		unused = new Map();
 
 		var varying = [];
 		var paramCount = 0, varCount = 0, inputCount = 0, outCount = 0, texCount = 0;
@@ -59,6 +61,7 @@ class AgalOut {
 				continue;
 			}
 			varMap.set(v.id, r);
+			unused.set(v.id, r);
 		}
 		if( paramCount != s.globalsSize + s.paramsSize )
 			throw "assert";
@@ -110,6 +113,17 @@ class AgalOut {
 				default:
 				}
 		}
+
+		// force write of unused inputs
+		for( r in unused )
+			switch( r.t ) {
+			case RAttr:
+				var t = allocReg();
+				t.swiz = r.swiz == null ? null : [for( i in 0...r.swiz.length ) COMPS[i]];
+				op(OMov(t, r));
+			default:
+			}
+
 		return {
 			fragmentShader : !current.vertex,
 			version : version,
@@ -381,6 +395,8 @@ class AgalOut {
 			return unop(OSin);
 		case [Cos, _]:
 			return unop(OCos);
+		case [Fract, _]:
+			return unop(OFrc);
 		case [Clamp, [a, min, max]]:
 			var r = allocReg(ret);
 			op(OMax(r, expr(a), expr(min)));
@@ -561,7 +577,10 @@ class AgalOut {
 
 	function reg( v : TVar ) : Reg {
 		var r = varMap.get(v.id);
-		if( r != null ) return r;
+		if( r != null ) {
+			unused.remove(v.id);
+			return r;
+		}
 		if( v.kind != Local ) throw "assert " + v;
 		r = allocReg(v.type);
 		varMap.set(v.id, r);