Quellcode durchsuchen

added hxsl switch support, fixed dynamic "for" handling in GLSL

ncannasse vor 8 Jahren
Ursprung
Commit
ec770dfb95
9 geänderte Dateien mit 201 neuen und 3 gelöschten Zeilen
  1. 16 0
      hxsl/Ast.hx
  2. 10 0
      hxsl/Checker.hx
  3. 34 0
      hxsl/Eval.hx
  4. 26 1
      hxsl/GlslOut.hx
  5. 2 0
      hxsl/Linker.hx
  6. 2 0
      hxsl/MacroParser.hx
  7. 30 2
      hxsl/Printer.hx
  8. 6 0
      hxsl/Splitter.hx
  9. 75 0
      samples/Pbr.hx

+ 16 - 0
hxsl/Ast.hx

@@ -128,6 +128,7 @@ enum ExprDef {
 	EContinue;
 	EArray( e : Expr, eindex : Expr );
 	EArrayDecl( el : Array<Expr> );
+	ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr:Expr }>, def : Null<Expr> );
 }
 
 typedef TVar = {
@@ -251,6 +252,7 @@ enum TExprDef {
 	TBreak;
 	TArray( e : TExpr, index : TExpr );
 	TArrayDecl( el : Array<TExpr> );
+	TSwitch( e : TExpr, cases : Array<{ values : Array<TExpr>, expr:TExpr }>, def : Null<TExpr> );
 }
 
 typedef TExpr = { e : TExprDef, t : Type, p : Position }
@@ -386,6 +388,12 @@ class Tools {
 			return false;
 		case TVarDecl(_), TCall(_), TDiscard, TContinue, TBreak, TReturn(_):
 			return true;
+		case TSwitch(e, cases, def):
+			for( c in cases ) {
+				for( v in c.values ) if( hasSideEffect(v) ) return true;
+				if( hasSideEffect(c.expr) ) return true;
+			}
+			return hasSideEffect(e) || (def != null && hasSideEffect(def));
 		}
 	}
 
@@ -403,6 +411,13 @@ class Tools {
 		case TFor(_, it, loop): f(it); f(loop);
 		case TArray(e, index): f(e); f(index);
 		case TArrayDecl(el): for( e in el ) f(e);
+		case TSwitch(e, cases, def):
+			f(e);
+			for( c in cases ) {
+				for( v in c.values ) f(v);
+				f(c.expr);
+			}
+			if( def != null ) f(def);
 		case TConst(_),TVar(_),TGlobal(_), TDiscard, TContinue, TBreak:
 		}
 	}
@@ -421,6 +436,7 @@ class Tools {
 		case TFor(v, it, loop): TFor(v, f(it), f(loop));
 		case TArray(e, index): TArray(f(e), f(index));
 		case TArrayDecl(el): TArrayDecl([for( e in el ) f(e)]);
+		case TSwitch(e, cases, def): TSwitch(f(e), [for( c in cases ) { values : [for( v in c.values ) f(v)], expr : f(c.expr) }], def == null ? null : f(def));
 		case TConst(_), TVar(_), TGlobal(_), TDiscard, TContinue, TBreak: e.e;
 		}
 		return { e : ed, t : e.t, p : e.p };

+ 10 - 0
hxsl/Checker.hx

@@ -502,6 +502,12 @@ class Checker {
 				unifyExpr(el[i], t);
 			type = TArray(t, SConst(el.length));
 			TArrayDecl(el);
+		case ESwitch(e, cases, def):
+			var et = typeExpr(e, Value);
+			var cases = [for( c in cases ) { values : [for( v in c.values ) typeWith(v, et.t)], expr : typeExpr(c.expr, with) }];
+			var def = def == null ? null : typeExpr(def, with);
+			type = TVoid;
+			TSwitch(et, cases, def);
 		}
 		if( type == null ) throw "assert";
 		return { e : ed, t : type, p : e.pos };
@@ -983,6 +989,10 @@ class Checker {
 			unifyExpr(e1, TInt);
 			unifyExpr(e2, TInt);
 			TArray(TInt, SConst(0));
+		case OpShl, OpShr, OpUShr, OpOr, OpAnd, OpXor:
+			unifyExpr(e1, TInt);
+			unifyExpr(e2, TInt);
+			TInt;
 		default:
 			error("Unsupported operator " + op, pos);
 		}

+ 34 - 0
hxsl/Eval.hx

@@ -384,6 +384,40 @@ class Eval {
 			}
 			varMap.remove(v);
 			e;
+		case TSwitch(e, cases, def):
+			var e = evalExpr(e);
+			var cases = [for( c in cases ) { values : [for( v in c.values ) evalExpr(v)], expr : evalExpr(c.expr, isVal) }];
+			var def = def == null ? null : evalExpr(def, isVal);
+			var hasCase = false;
+			switch( e.e ) {
+			case TConst(c):
+				switch( c ) {
+				case CInt(val):
+					for( c in cases ) {
+						for( v in c.values )
+							switch( v.e ) {
+							case TConst(cst):
+								switch( cst ) {
+								case CInt(k) if( k == val ): return c.expr;
+								case CFloat(k) if( k == val ): return c.expr;
+								default:
+								}
+							default:
+								hasCase = true;
+							}
+					}
+				default:
+					throw "Unsupported switch constant "+c;
+				}
+			default:
+				hasCase = true;
+			}
+			if( hasCase )
+				TSwitch(e, cases, def);
+			else if( def == null )
+				TBlock([]);
+			else
+				def.e;
 		case TArrayDecl(el):
 			TArrayDecl([for( e in el ) evalExpr(e)]);
 		};

+ 26 - 1
hxsl/GlslOut.hx

@@ -240,6 +240,13 @@ class GlslOut {
 				add(",");
 				addValue(e2, tabs);
 				add(")");
+			case [OpUShr, _, _]:
+				decl("int _ushr( uint i, uint j ) { return int(i >> j); }");
+				add("_ushr(");
+				addValue(e1, tabs);
+				add(",");
+				addValue(e2, tabs);
+				add(")");
 			case [OpEq | OpNotEq | OpLt | OpGt | OpLte | OpGte, TVec(n, _), TVec(_)]:
 				add("vec" + n + "(");
 				add(switch( op ) {
@@ -355,7 +362,25 @@ class GlslOut {
 				addValue(e, tabs);
 			}
 		case TFor(v, it, loop):
-			add("for(...)");
+			locals.set(v.id, v);
+			switch( it.e ) {
+			case TBinop(OpInterval, e1, e2):
+				add("for(");
+				add(v.name+"=");
+				addValue(e1,tabs);
+				add(";"+v.name+"<");
+				addValue(e2,tabs);
+				add(";" + v.name+"++) {");
+				tabs += "\t";
+				add("\n" + tabs);
+				addExpr(loop, tabs);
+				tabs = tabs.substr(1);
+				add("\n" + tabs+"}");
+			default:
+				throw "assert";
+			}
+		case TSwitch(_):
+			add("switch(...)");
 		case TContinue:
 			add("continue");
 		case TBreak:

+ 2 - 0
hxsl/Linker.hx

@@ -207,6 +207,8 @@ class Linker {
 			}
 		case TVarDecl(v, _):
 			locals.set(v.id, true);
+		case TFor(v, _, _):
+			locals.set(v.id, true);
 		default:
 		}
 		return e.map(mapExprVar);

+ 2 - 0
hxsl/MacroParser.hx

@@ -218,6 +218,8 @@ class MacroParser {
 			EArray(parseExpr(e1), parseExpr(e2));
 		case EArrayDecl(el):
 			EArrayDecl([for( e in el ) parseExpr(e)]);
+		case ESwitch(e, cases, def):
+			ESwitch(parseExpr(e), [for( c in cases ) { expr : parseExpr(c.expr), values : [for( v in c.values ) parseExpr(v)] }], def == null ? null : parseExpr(def));
 		default:
 			null;
 		};

+ 30 - 2
hxsl/Printer.hx

@@ -169,10 +169,38 @@ class Printer {
 			}
 			add(")");
 		case TFor(v, it, loop):
-			add("for( " + v.name + " in ");
+			add("for( ");
+			addVarName(v);
+			add(" in ");
 			addExpr(it, tabs);
-			add(") ");
+			add(" ) ");
 			addExpr(loop, tabs);
+		case TSwitch(e, cases, def):
+			add("switch( ");
+			addExpr(e, tabs);
+			add(") {");
+			var old = tabs;
+			for( c in cases ) {
+				add("\n" + tabs);
+				add("case ");
+				var first = true;
+				for( v in c.values ) {
+					if( first ) first = false else add(", ");
+					addExpr(v, tabs);
+				}
+				tabs += "\t";
+				add(":\n"+tabs);
+				addExpr(c.expr, tabs);
+				tabs = old;
+			}
+			if( def != null ) {
+				add("\n" + tabs);
+				tabs += "\t";
+				add("default:\n" + tabs);
+				addExpr(def, tabs);
+				tabs = old;
+			}
+			add("\n" + tabs + "}");
 		case TContinue:
 			add("continue");
 		case TBreak:

+ 6 - 0
hxsl/Splitter.hx

@@ -251,6 +251,12 @@ class Splitter {
 				checkExpr(init);
 				inf.write++;
 			}
+		case TFor(v, it, loop):
+			checkExpr(it);
+			var inf = get(v);
+			inf.local = true;
+			inf.write++;
+			checkExpr(loop);
 		default:
 			e.iter(checkExpr);
 		}

+ 75 - 0
samples/Pbr.hx

@@ -140,6 +140,68 @@ class PbrShader extends hxsl.Shader {
 
 }
 
+class Irradiance extends h3d.shader.ScreenShader {
+
+	static var SRC = {
+
+		@const var face : Int;
+		@const var samplesBits : Int;
+		@param var envMap : SamplerCube;
+
+		function _reversebits( i : Int ) : Int {
+			var r = (i << 16) | (i >>> 16);
+			r = ((r & 0x00ff00ff) << 8) | ((r & 0xff00ff00) >>> 8);
+			r = ((r & 0x0f0f0f0f) << 4) | ((r & 0xf0f0f0f0) >>> 4);
+			r = ((r & 0x33333333) << 2) | ((r & 0xcccccccc) >>> 2);
+			r = ((r & 0x55555555) << 1) | ((r & 0xaaaaaaaa) >>> 1);
+			return r;
+		}
+
+		function hammersley( i : Int, max : Int ) : Vec2 {
+			var ri = _reversebits(i) * 2.3283064365386963e-10;
+			return vec2(float(i) / float(max), ri);
+		}
+
+		function cosineWeightedSampling( p : Vec2 ) : Vec3 {
+			var sq = sqrt(1 - p.x);
+			var alpha = 2 * PI * p.y;
+			return vec3( sq * cos(alpha),  sq * sin(alpha), sqrt(p.x));
+		}
+
+		function getNormal() : Vec3 {
+			var d = input.uv * 2. - 1.;
+			var n : Vec3;
+			switch( face ) {
+			case 0: n = vec3(1, -d.y, -d.x);
+			default: n = vec3( -d.x, -d.y, -1);
+			}
+			return n.normalize();
+		}
+
+		function fragment() {
+			var color = vec3(0.);
+			var n = getNormal();
+			var up = abs(n.z) < 0.999 ? vec3(0, 0, 1) : vec3(1, 0, 0);
+			var tanX = normalize(cross(up, n));
+			var tanY = cross(n, tanX);
+			var totalWeight = 1e-10;
+			var numSamples = 1 << samplesBits;
+			for( i in 0...numSamples ) {
+				var p = hammersley(i, numSamples);
+				var ltan = cosineWeightedSampling(p);
+				var l = normalize(tanX * ltan.x + tanY * ltan.y + n * ltan.z);
+				var amount = n.dot(l);
+				color += envMap.get(l).rgb * amount;
+				totalWeight += amount;
+			}
+			output.color = vec4(color / totalWeight, 1.);
+		}
+
+	}
+
+}
+
+
 class Pbr extends hxd.App {
 
 	var fui : h2d.Flow;
@@ -214,6 +276,19 @@ class Pbr extends hxd.App {
 		set(5, hxd.Res.bottom);
 
 		shader.cubeMap = cube;
+
+
+		var irradDiffuse = new h3d.mat.Texture(128, 128, [Cubic]);
+		var screen = new h3d.pass.ScreenFx(new Irradiance());
+		screen.shader.samplesBits = 8;
+		screen.shader.envMap = cube;
+		for( i in 0...6 ) {
+			screen.shader.face = i;
+			engine.driver.setRenderTarget(irradDiffuse, i);
+			screen.render();
+		}
+		engine.driver.setRenderTarget(null);
+
 		bg.material.mainPass.addShader(new h3d.shader.CubeMap(cube));
 
 		shader.metalness = 0.2;