Pārlūkot izejas kodu

Move globals from Default to context

Nicolas Cannasse 1 gadu atpakaļ
vecāks
revīzija
fb187befd8

+ 1 - 1
h2d/Drawable.hx

@@ -146,7 +146,7 @@ class Drawable extends Object {
 	public function getDebugShaderCode( toHxsl = true ) {
 		var shader = @:privateAccess {
 			var ctx = getScene().ctx;
-			ctx.manager.compileShaders(new hxsl.ShaderList(ctx.baseShader,shaders));
+			ctx.manager.compileShaders(ctx.globals, new hxsl.ShaderList(ctx.baseShader,shaders));
 		}
 		if( toHxsl ) {
 			var toString = hxsl.Printer.shaderToString.bind(_, true);

+ 9 - 8
h2d/RenderContext.hx

@@ -173,12 +173,12 @@ class RenderContext extends h3d.impl.RenderContext {
 		viewD = scene.viewportD;
 		viewX = scene.viewportX;
 		viewY = scene.viewportY;
-
+		setCurrent();
 		targetFlipY = engine.driver.hasFeature(BottomLeftCoords) ? -1 : 1;
 		baseFlipY = engine.getCurrentTarget() != null ? targetFlipY : 1;
 		inFilter = null;
-		manager.globals.set("time", time);
-		manager.globals.set("global.time", time);
+		globals.set("time", time);
+		globals.set("global.time", time);
 		baseShader.pixelAlign = false;
 		baseShader.halfPixelInverse.set(0.5 / engine.width, 0.5 / engine.height);
 		baseShader.viewportA.set(scene.viewportA, 0, scene.viewportX);
@@ -210,12 +210,12 @@ class RenderContext extends h3d.impl.RenderContext {
 
 	function initShaders( shaders ) {
 		currentShaders = shaders;
-		compiledShader = manager.compileShaders(shaders);
+		compiledShader = manager.compileShaders(globals, shaders);
 		if( buffers == null )
 			buffers = new h3d.shader.Buffers(compiledShader);
 		else
 			buffers.grow(compiledShader);
-		manager.fillGlobals(buffers, compiledShader);
+		fillGlobals(buffers, compiledShader);
 		engine.selectShader(compiledShader);
 		engine.uploadShaderBuffers(buffers, Globals);
 	}
@@ -230,6 +230,7 @@ class RenderContext extends h3d.impl.RenderContext {
 		texture = null;
 		currentObj = null;
 		baseShaderList.next = null;
+		clearCurrent();
 		if ( targetsStackIndex != 0 ) throw "Missing popTarget()";
 		if ( cameraStackIndex != 0 ) throw "Missing popCamera()";
 	}
@@ -611,7 +612,7 @@ class RenderContext extends h3d.impl.RenderContext {
 					pass.blendSrc = One;
 			}
 		}
-		manager.fillParams(buffers, compiledShader, currentShaders);
+		fillParams(buffers, compiledShader, currentShaders);
 		engine.selectMaterial(pass);
 		engine.uploadShaderBuffers(buffers, Params);
 		engine.uploadShaderBuffers(buffers, Textures);
@@ -773,7 +774,7 @@ class RenderContext extends h3d.impl.RenderContext {
 			var prevInst = @:privateAccess t.instance;
 			if( s != t )
 				paramsChanged = true;
-			s.updateConstants(manager.globals);
+			s.updateConstants(globals);
 			if( @:privateAccess s.instance != prevInst )
 				shaderChanged = true;
 		}
@@ -784,7 +785,7 @@ class RenderContext extends h3d.impl.RenderContext {
 			baseShader.hasUVPos = hasUVPos;
 			baseShader.isRelative = isRelative;
 			baseShader.killAlpha = killAlpha;
-			baseShader.updateConstants(manager.globals);
+			baseShader.updateConstants(globals);
 			baseShaderList.next = obj.shaders;
 			initShaders(baseShaderList);
 		} else if( paramsChanged ) {

+ 3 - 0
h2d/Scene.hx

@@ -739,6 +739,7 @@ class Scene extends Layers implements h3d.IDrawable implements hxd.SceneEvents.I
 		var inRender = @:privateAccess ctx.engine.inRender;
 		ctx.engine.backgroundColor = null; // prevent clear bg
 		ctx.globalAlpha = alpha;
+		var prevCtx = h3d.impl.RenderContext.get();
 		if( !inRender ) { // don't reset current tex stack
 			ctx.engine.begin();
 			ctx.begin();
@@ -754,6 +755,8 @@ class Scene extends Layers implements h3d.IDrawable implements hxd.SceneEvents.I
 			ctx.end();
 			ctx.engine.end();
 		}
+		if( prevCtx != null )
+			prevCtx.setCurrent();
 	}
 
 	/**

+ 272 - 1
h3d/impl/RenderContext.hx

@@ -2,21 +2,292 @@ package h3d.impl;
 
 class RenderContext {
 
+	public static var STRICT = true;
+
 	public var engine : h3d.Engine;
 	public var time : Float;
 	public var elapsedTime : Float;
 	public var frame : Int;
 	public var textures : h3d.impl.TextureCache;
+	public var globals : hxsl.Globals;
 
 	function new() {
 		engine = h3d.Engine.getCurrent();
 		frame = 0;
 		time = 0.;
 		elapsedTime = 1. / hxd.System.getDefaultFrameRate();
-		textures = new h3d.impl.TextureCache(this);
+		textures = new h3d.impl.TextureCache();
+		globals = new hxsl.Globals();
+	}
+
+	public function setCurrent() {
+		inst = this;
+	}
+
+	public function clearCurrent() {
+		if( inst == this )
+			inst = null;
+		else
+			throw "Context has changed";
 	}
 
 	public function dispose() {
 		textures.dispose();
 	}
+
+	function fillRec( v : Dynamic, type : hxsl.Ast.Type, out : #if hl hl.BytesAccess<hl.F32> #else h3d.shader.Buffers.ShaderBufferData #end, pos : Int ) {
+		switch( type ) {
+		case TInt:
+			out[pos] = v;
+			return 1;
+		case TFloat:
+			out[pos] = v;
+			return 1;
+		case TVec(4, _):
+			var v : hxsl.Types.Vec4 = v;
+			out[pos++] = v.x;
+			out[pos++] = v.y;
+			out[pos++] = v.z;
+			out[pos++] = v.w;
+			return 4;
+		case TVec(n, _):
+			var v : hxsl.Types.Vec = v;
+			out[pos++] = v.x;
+			out[pos++] = v.y;
+			if( n == 3 )
+				out[pos++] = v.z;
+			return n;
+		case TMat4:
+			var m : h3d.Matrix = v;
+			out[pos++] = m._11;
+			out[pos++] = m._21;
+			out[pos++] = m._31;
+			out[pos++] = m._41;
+			out[pos++] = m._12;
+			out[pos++] = m._22;
+			out[pos++] = m._32;
+			out[pos++] = m._42;
+			out[pos++] = m._13;
+			out[pos++] = m._23;
+			out[pos++] = m._33;
+			out[pos++] = m._43;
+			out[pos++] = m._14;
+			out[pos++] = m._24;
+			out[pos++] = m._34;
+			out[pos++] = m._44;
+			return 16;
+		case TMat3x4:
+			var m : h3d.Matrix = v;
+			out[pos++] = m._11;
+			out[pos++] = m._21;
+			out[pos++] = m._31;
+			out[pos++] = m._41;
+			out[pos++] = m._12;
+			out[pos++] = m._22;
+			out[pos++] = m._32;
+			out[pos++] = m._42;
+			out[pos++] = m._13;
+			out[pos++] = m._23;
+			out[pos++] = m._33;
+			out[pos++] = m._43;
+			return 12;
+		case TMat3:
+			var m : h3d.Matrix = v;
+			out[pos++] = m._11;
+			out[pos++] = m._21;
+			out[pos++] = m._31;
+			out[pos++] = 0;
+			out[pos++] = m._12;
+			out[pos++] = m._22;
+			out[pos++] = m._32;
+			out[pos++] = 0;
+			out[pos++] = m._13;
+			out[pos++] = m._23;
+			out[pos++] = m._33;
+			out[pos++] = 0;
+			return 12;
+		case TArray(TVec(4,VFloat), SConst(len)):
+			var v : Array<h3d.Vector4> = v;
+			for( i in 0...len ) {
+				var n = v[i];
+				if( n == null ) break;
+				out[pos++] = n.x;
+				out[pos++] = n.y;
+				out[pos++] = n.z;
+				out[pos++] = n.w;
+			}
+			return len * 4;
+		case TArray(TMat3x4, SConst(len)):
+			var v : Array<h3d.Matrix> = v;
+			for( i in 0...len ) {
+				var m = v[i];
+				if( m == null ) break;
+				out[pos++] = m._11;
+				out[pos++] = m._21;
+				out[pos++] = m._31;
+				out[pos++] = m._41;
+				out[pos++] = m._12;
+				out[pos++] = m._22;
+				out[pos++] = m._32;
+				out[pos++] = m._42;
+				out[pos++] = m._13;
+				out[pos++] = m._23;
+				out[pos++] = m._33;
+				out[pos++] = m._43;
+			}
+			return len * 12;
+		case TArray(TFloat, SConst(len)):
+			var v : Array<Float> = v;
+			var size = 0;
+			var count = v.length < len ? v.length : len;
+			for( i in 0...count )
+				out[pos++] = v[i];
+			return len;
+		case TArray(t, SConst(len)):
+			var v : Array<Dynamic> = v;
+			var size = 0;
+			for( i in 0...len ) {
+				var n = v[i];
+				if( n == null ) break;
+				size = fillRec(n, t, out, pos);
+				pos += size;
+			}
+			return len * size;
+		case TStruct(vl):
+			var tot = 0;
+			for( vv in vl )
+				tot += fillRec(Reflect.field(v, vv.name), vv.type, out, pos + tot);
+			return tot;
+		default:
+			throw "assert " + type;
+		}
+		return 0;
+	}
+
+	function shaderInfo( shaders : hxsl.ShaderList, path : String ) {
+		var name = path.split(".").pop();
+		while( shaders != null ) {
+			var inst = @:privateAccess shaders.s.instance;
+			for( v in inst.shader.vars )
+				if( v.name == name )
+					return shaders.s.toString();
+			shaders = shaders.next;
+		}
+		return "(not found)";
+	}
+
+	inline function getPtr( data : h3d.shader.Buffers.ShaderBufferData ) {
+		#if hl
+		return (hl.Bytes.getArray((cast data : Array<Single>)) : hl.BytesAccess<hl.F32>);
+		#else
+		return data;
+		#end
+	}
+
+	public inline function getParamValue( p : hxsl.RuntimeShader.AllocParam, shaders : hxsl.ShaderList, opt = false ) : Dynamic {
+		if( p.perObjectGlobal != null ) {
+			var v : Dynamic = globals.fastGet(p.perObjectGlobal.gid);
+			if( v == null ) throw "Missing global value " + p.perObjectGlobal.path+" for shader "+shaderInfo(shaders,p.perObjectGlobal.path);
+			if( p.type.match(TChannel(_)) )
+				return v.texture;
+			return v;
+		}
+		var si = shaders;
+		var n = p.instance;
+		while( --n > 0 ) si = si.next;
+		var v = si.s.getParamValue(p.index);
+		if( v == null && !opt ) throw "Missing param value " + si.s + "." + p.name;
+		return v;
+	}
+
+	public function fillGlobals( buf : h3d.shader.Buffers, s : hxsl.RuntimeShader ) {
+		inline function fill(buf:h3d.shader.Buffers.ShaderBuffers, s:hxsl.RuntimeShader.RuntimeShaderData) {
+			var g = s.globals;
+			var ptr = getPtr(buf.globals);
+			while( g != null ) {
+				var v = globals.fastGet(g.gid);
+				if( v == null )
+					throw "Missing global value " + g.path;
+				fillRec(v, g.type, ptr, g.pos);
+				g = g.next;
+			}
+		}
+		fill(buf.vertex, s.vertex);
+		fill(buf.fragment, s.fragment);
+	}
+
+	public function fillParams( buf : h3d.shader.Buffers, s : hxsl.RuntimeShader, shaders : hxsl.ShaderList ) {
+		var curInstance = -1;
+		var curInstanceValue = null;
+		inline function getInstance( index : Int ) {
+			if( curInstance == index )
+				return curInstanceValue;
+			var si = shaders;
+			curInstance = index;
+			while( --index > 0 ) si = si.next;
+			curInstanceValue = si.s;
+			return curInstanceValue;
+		}
+		inline function getParamValue( p : hxsl.RuntimeShader.AllocParam, shaders : hxsl.ShaderList, opt = false ) : Dynamic {
+			if( p.perObjectGlobal != null ) {
+				var v : Dynamic = globals.fastGet(p.perObjectGlobal.gid);
+				if( v == null ) throw "Missing global value " + p.perObjectGlobal.path+" for shader "+shaderInfo(shaders,p.perObjectGlobal.path);
+				if( p.type.match(TChannel(_)) )
+					return v.texture;
+				return v;
+			}
+			var v = getInstance(p.instance).getParamValue(p.index);
+			if( v == null && !opt ) throw "Missing param value " + shaders.s + "." + p.name;
+			return v;
+		}
+		inline function fill(buf:h3d.shader.Buffers.ShaderBuffers, s:hxsl.RuntimeShader.RuntimeShaderData) {
+			var p = s.params;
+			var ptr = getPtr(buf.params);
+			while( p != null ) {
+				var v : Dynamic;
+				if( p.perObjectGlobal == null ) {
+					if( p.type == TFloat ) {
+						var i = getInstance(p.instance);
+						ptr[p.pos] = i.getParamFloatValue(p.index);
+						p = p.next;
+						continue;
+					}
+					v = getInstance(p.instance).getParamValue(p.index);
+					if( v == null ) throw "Missing param value " + curInstanceValue + "." + p.name;
+				} else
+					v = getParamValue(p, shaders);
+				fillRec(v, p.type, ptr, p.pos);
+				p = p.next;
+			}
+			var tid = 0;
+			var p = s.textures;
+			while( p != null ) {
+				var t : Dynamic = getParamValue(p, shaders, !STRICT);
+				if( p.pos < 0 ) {
+					// is array !
+					var arr : Array<h3d.mat.Texture> = t;
+					for( i in 0...-p.pos )
+						buf.tex[tid++] = arr[i];
+				} else
+					buf.tex[tid++] = t;
+				p = p.next;
+			}
+			var p = s.buffers;
+			var bid = 0;
+			while( p != null ) {
+				var b : h3d.Buffer = getParamValue(p, shaders, !STRICT);
+				buf.buffers[bid++] = b;
+				p = p.next;
+			}
+		}
+		fill(buf.vertex, s.vertex);
+		fill(buf.fragment, s.fragment);
+	}
+
+	static var inst : RenderContext;
+	public static function get() return inst;
+	public static inline function getType<T:RenderContext>( cl : Class<h3d.impl.RenderContext> ) {
+		return Std.downcast(inst, cl);
+	}
+
 }

+ 1 - 3
h3d/impl/TextureCache.hx

@@ -5,11 +5,9 @@ class TextureCache {
 	var cache : Array<h3d.mat.Texture>;
 	var position : Int = 0;
 	var defaultDepthBuffer : h3d.mat.Texture;
-	var ctx : h3d.impl.RenderContext;
 	public var defaultFormat : hxd.PixelFormat;
 
-	public function new(ctx) {
-		this.ctx = ctx;
+	public function new() {
 		cache = [];
 		var engine = h3d.Engine.getCurrent();
 		defaultFormat = h3d.mat.Texture.nativeFormat;

+ 4 - 5
h3d/pass/CascadeShadowMap.hx

@@ -90,11 +90,6 @@ class CascadeShadowMap extends DirShadowMap {
 		lightCameras[cascade - 1].orthoBounds = lightCamera.orthoBounds.clone();
 	}
 
-	override function setGlobals() {
-		super.setGlobals();
-		cameraViewProj = getCascadeProj(currentCascadeIndex);
-	}
-
 	function getCascadeProj(i:Int) {
 		return lightCameras[i].m;
 	}
@@ -125,6 +120,10 @@ class CascadeShadowMap extends DirShadowMap {
 		cshader.pcfQuality = pcfQuality;
 	}
 
+	override function getShadowProj():Matrix {
+		return getCascadeProj(currentCascadeIndex);
+	}
+
 	override function draw( passes, ?sort ) {
 		if( !enabled )
 			return;

+ 7 - 7
h3d/pass/CubeShadowMap.hx

@@ -50,13 +50,6 @@ class CubeShadowMap extends Shadows {
 		return true;
 	}
 
-	override function setGlobals() {
-		super.setGlobals();
-		cameraViewProj = getShadowProj();
-		cameraFar = lightCamera.zFar;
-		cameraPos = lightCamera.pos;
-	}
-
 	override function saveStaticData() {
 		if( mode != Mixed && mode != Static )
 			return null;
@@ -180,6 +173,10 @@ class CubeShadowMap extends Shadows {
 		lightCamera.pos.set(absPos.tx, absPos.ty, absPos.tz);
 		updateLightCameraNearFar(light);
 
+		var prevFar = @:privateAccess ctx.cameraFar;
+		var prevPos = @:privateAccess ctx.cameraPos;
+		@:privateAccess ctx.cameraFar = lightCamera.zFar;
+		@:privateAccess ctx.cameraPos = lightCamera.pos;
 
 		for( i in 0...6 ) {
 
@@ -207,6 +204,9 @@ class CubeShadowMap extends Shadows {
 			ctx.engine.popTarget();
 		}
 
+		@:privateAccess ctx.cameraFar = prevFar;
+		@:privateAccess ctx.cameraPos = prevPos;
+
 		// Blur is applied even if there's no shadows - TO DO : remove the useless blur pass
 		if( blur.radius > 0 )
 			blur.apply(ctx, texture);

+ 10 - 34
h3d/pass/Default.hx

@@ -1,6 +1,5 @@
 package h3d.pass;
 
-@:build(hxsl.Macros.buildGlobals())
 @:access(h3d.mat.Pass)
 class Default extends Base {
 
@@ -8,31 +7,11 @@ class Default extends Base {
 	var globals(get, never) : hxsl.Globals;
 	var defaultSort = new SortByMaterial().sort;
 
-	inline function get_globals() return manager.globals;
-
-	@global("camera.view") var cameraView : h3d.Matrix = ctx.camera.mcam;
-	@global("camera.zNear") var cameraNear : Float = ctx.camera.zNear;
-	@global("camera.zFar") var cameraFar : Float = ctx.camera.zFar;
-	@global("camera.proj") var cameraProj : h3d.Matrix = ctx.camera.mproj;
-	@global("camera.position") var cameraPos : h3d.Vector = ctx.camera.pos;
-	@global("camera.projDiag") var cameraProjDiag : h3d.Vector4 = new h3d.Vector4(ctx.camera.mproj._11,ctx.camera.mproj._22,ctx.camera.mproj._33,ctx.camera.mproj._44);
-	@global("camera.projFlip") var cameraProjFlip : Float = ctx.engine.driver.hasFeature(BottomLeftCoords) && ctx.engine.getCurrentTarget() != null ? -1 : 1;
-	@global("camera.viewProj") var cameraViewProj : h3d.Matrix = ctx.camera.m;
-	@global("camera.inverseViewProj") var cameraInverseViewProj : h3d.Matrix = ctx.camera.getInverseViewProj();
-	@global("global.time") var globalTime : Float = ctx.time;
-	@global("global.pixelSize") var pixelSize : h3d.Vector = getCurrentPixelSize();
-	@global("global.modelView") var globalModelView : h3d.Matrix;
-	@global("global.modelViewInverse") var globalModelViewInverse : h3d.Matrix;
+	inline function get_globals() return ctx.globals;
 
 	public function new(name) {
 		super(name);
 		manager = new ShaderManager(getOutputs());
-		initGlobals();
-	}
-
-	function getCurrentPixelSize() {
-		var t = ctx.engine.getCurrentTarget();
-		return new h3d.Vector(2 / (t == null ? ctx.engine.width : t.width), 2 / (t == null ? ctx.engine.height : t.height));
 	}
 
 	function getOutputs() : Array<hxsl.Output> {
@@ -43,7 +22,7 @@ class Default extends Base {
 		var o = @:privateAccess new h3d.pass.PassObject();
 		o.pass = p;
 		setupShaders(new h3d.pass.PassList(o));
-		return manager.compileShaders(o.shaders, p.batchMode ? Batch : Default);
+		return manager.compileShaders(ctx.globals, o.shaders, p.batchMode ? Batch : Default);
 	}
 
 	function processShaders( p : h3d.pass.PassObject, shaders : hxsl.ShaderList ) {
@@ -68,13 +47,13 @@ class Default extends Base {
 				}
 				shaders = ctx.lightSystem.computeLight(p.obj, shaders);
 			}
-			p.shader = manager.compileShaders(shaders, p.pass.batchMode ? Batch : Default);
+			p.shader = manager.compileShaders(ctx.globals, shaders, p.pass.batchMode ? Batch : Default);
 			p.shaders = shaders;
 			var t = p.shader.fragment.textures;
 			if( t == null || t.type.match(TArray(_)) )
 				p.texture = 0;
 			else {
-				var t : h3d.mat.Texture = manager.getParamValue(t, shaders, true);
+				var t : h3d.mat.Texture = ctx.getParamValue(t, shaders, true);
 				p.texture = t == null ? 0 : t.id;
 			}
 		}
@@ -97,21 +76,18 @@ class Default extends Base {
 		if( passes.isEmpty() )
 			return;
 		#if sceneprof h3d.impl.SceneProf.begin("draw", ctx.frame); #end
-		for( g in ctx.sharedGlobals )
-			globals.fastSet(g.gid, g.value);
-		setGlobals();
+		ctx.setupTarget();
 		setupShaders(passes);
 		if( sort == null )
 			defaultSort(passes);
 		else
 			sort(passes);
-		ctx.currentManager = manager;
 		var buf = ctx.shaderBuffers, prevShader = null;
 		for( p in passes ) {
 			#if sceneprof h3d.impl.SceneProf.mark(p.obj); #end
-			globalModelView = p.obj.absPos;
-			if( p.shader.hasGlobal(globalModelViewInverse_id.toInt()) )
-				globalModelViewInverse = p.obj.getInvPos();
+			ctx.globalModelView = p.obj.absPos;
+			if( p.shader.hasGlobal(ctx.globalModelViewInverse_id.toInt()) )
+				ctx.globalModelViewInverse = p.obj.getInvPos();
 			if( prevShader != p.shader ) {
 				prevShader = p.shader;
 				if( onShaderError != null ) {
@@ -128,11 +104,11 @@ class Default extends Base {
 					buf = ctx.shaderBuffers = new h3d.shader.Buffers(p.shader);
 				else
 					buf.grow(p.shader);
-				manager.fillGlobals(buf, p.shader);
+				ctx.fillGlobals(buf, p.shader);
 				ctx.engine.uploadShaderBuffers(buf, Globals);
 			}
 			if( !p.pass.dynamicParameters ) {
-				manager.fillParams(buf, p.shader, p.shaders);
+				ctx.fillParams(buf, p.shader, p.shaders);
 				ctx.engine.uploadShaderBuffers(buf, Params);
 				ctx.engine.uploadShaderBuffers(buf, Textures);
 				ctx.engine.uploadShaderBuffers(buf, Buffers);

+ 5 - 5
h3d/pass/DefaultShadowMap.hx

@@ -26,11 +26,11 @@ class DefaultShadowMap extends DirShadowMap {
 
 	override function draw( passes, ?sort ) {
 		super.draw(passes, sort);
-		ctx.setGlobalID(shadowMapId, { texture : dshader.shadowMap, channel : format == h3d.mat.Texture.nativeFormat ? hxsl.Channel.PackedFloat : hxsl.Channel.R });
-		ctx.setGlobalID(shadowProjId, getShadowProj());
-		ctx.setGlobalID(shadowColorId, color);
-		ctx.setGlobalID(shadowPowerId, power);
-		ctx.setGlobalID(shadowBiasId, bias);
+		ctx.globals.fastSet(shadowMapId, { texture : dshader.shadowMap, channel : format == h3d.mat.Texture.nativeFormat ? hxsl.Channel.PackedFloat : hxsl.Channel.R });
+		ctx.globals.fastSet(shadowProjId, getShadowProj());
+		ctx.globals.fastSet(shadowColorId, color);
+		ctx.globals.fastSet(shadowPowerId, power);
+		ctx.globals.fastSet(shadowBiasId, bias);
 	}
 
 }

+ 5 - 5
h3d/pass/DirShadowMap.hx

@@ -186,11 +186,6 @@ class DirShadowMap extends Shadows {
 		bounds.scaleCenter(1.01);
 	}
 
-	override function setGlobals() {
-		super.setGlobals();
-		cameraViewProj = getShadowProj();
-	}
-
 	override function syncShader(texture) {
 		dshader.shadowMap = texture;
 		dshader.shadowMapChannel = format == h3d.mat.Texture.nativeFormat ? PackedFloat : R;
@@ -266,6 +261,8 @@ class DirShadowMap extends Shadows {
 	}
 
 	function processShadowMap( passes, tex, ?sort) {
+		var prevViewProj = @:privateAccess ctx.cameraViewProj;
+		@:privateAccess ctx.cameraViewProj = getShadowProj();
 		if ( tex.isDepth() ) {
 			ctx.engine.pushDepth(tex);
 			ctx.engine.clear(null, 1.0);
@@ -306,6 +303,9 @@ class DirShadowMap extends Shadows {
 				ctx.engine.popTarget();
 			}
 		}
+
+		@:privateAccess ctx.cameraViewProj = prevViewProj;
+
 		return tex;
 	}
 

+ 12 - 8
h3d/pass/ScreenFx.hx

@@ -27,11 +27,6 @@ class ScreenFx<T:h3d.shader.ScreenShader> {
 		h3d.pass.Copy.run(src,dst);
 	}
 
-	public function setGlobals( ctx :  h3d.scene.RenderContext ) {
-		for( g in @:privateAccess ctx.sharedGlobals )
-			manager.globals.fastSet(g.gid, g.value);
-	}
-
 	public inline function addShader<T:hxsl.Shader>(s:T) {
 		return pass.addShader(s);
 	}
@@ -49,20 +44,29 @@ class ScreenFx<T:h3d.shader.ScreenShader> {
 			primitive = h3d.prim.Plane2D.get();
 		shader.flipY = engine.driver.hasFeature(BottomLeftCoords) && engine.getCurrentTarget() != null ? -1 : 1;
 		var shaders = @:privateAccess pass.shaders;
-		var rts = manager.compileShaders(shaders);
+		var ctx = h3d.impl.RenderContext.get();
+		var isNewCtx = false;
+		if( ctx == null ) {
+			isNewCtx = true;
+			ctx = @:privateAccess new h3d.impl.RenderContext();
+			ctx.setCurrent();
+		}
+		var rts = manager.compileShaders(ctx.globals, shaders);
 		engine.selectMaterial(pass);
 		engine.selectShader(rts);
 		if( buffers == null )
 			buffers = new h3d.shader.Buffers(rts);
 		else
 			buffers.grow(rts);
-		manager.fillGlobals(buffers, rts);
-		manager.fillParams(buffers, rts, shaders);
+		ctx.fillGlobals(buffers, rts);
+		ctx.fillParams(buffers, rts, shaders);
 		engine.uploadShaderBuffers(buffers, Globals);
 		engine.uploadShaderBuffers(buffers, Params);
 		engine.uploadShaderBuffers(buffers, Textures);
 		engine.uploadShaderBuffers(buffers, Buffers);
 		primitive.render(engine);
+		if( isNewCtx )
+			ctx.clearCurrent();
 	}
 
 	public function dispose() {

+ 1 - 255
h3d/pass/ShaderManager.hx

@@ -2,15 +2,11 @@ package h3d.pass;
 
 class ShaderManager {
 
-	public static var STRICT = true;
-
-	public var globals : hxsl.Globals;
 	var shaderCache : hxsl.Cache;
 	var currentOutput : hxsl.ShaderList;
 
 	public function new(?output:Array<hxsl.Output>) {
 		shaderCache = hxsl.Cache.get();
-		globals = new hxsl.Globals();
 		currentOutput = new hxsl.ShaderList(null);
 		setOutput(output);
 	}
@@ -20,257 +16,7 @@ class ShaderManager {
 		currentOutput.s = shaderCache.getLinkShader(output);
 	}
 
-	@:noDebug
-	function fillRec( v : Dynamic, type : hxsl.Ast.Type, out : #if hl hl.BytesAccess<hl.F32> #else h3d.shader.Buffers.ShaderBufferData #end, pos : Int ) {
-		switch( type ) {
-		case TInt:
-			out[pos] = v;
-			return 1;
-		case TFloat:
-			out[pos] = v;
-			return 1;
-		case TVec(4, _):
-			var v : hxsl.Types.Vec4 = v;
-			out[pos++] = v.x;
-			out[pos++] = v.y;
-			out[pos++] = v.z;
-			out[pos++] = v.w;
-			return 4;
-		case TVec(n, _):
-			var v : hxsl.Types.Vec = v;
-			out[pos++] = v.x;
-			out[pos++] = v.y;
-			if( n == 3 )
-				out[pos++] = v.z;
-			return n;
-		case TMat4:
-			var m : h3d.Matrix = v;
-			out[pos++] = m._11;
-			out[pos++] = m._21;
-			out[pos++] = m._31;
-			out[pos++] = m._41;
-			out[pos++] = m._12;
-			out[pos++] = m._22;
-			out[pos++] = m._32;
-			out[pos++] = m._42;
-			out[pos++] = m._13;
-			out[pos++] = m._23;
-			out[pos++] = m._33;
-			out[pos++] = m._43;
-			out[pos++] = m._14;
-			out[pos++] = m._24;
-			out[pos++] = m._34;
-			out[pos++] = m._44;
-			return 16;
-		case TMat3x4:
-			var m : h3d.Matrix = v;
-			out[pos++] = m._11;
-			out[pos++] = m._21;
-			out[pos++] = m._31;
-			out[pos++] = m._41;
-			out[pos++] = m._12;
-			out[pos++] = m._22;
-			out[pos++] = m._32;
-			out[pos++] = m._42;
-			out[pos++] = m._13;
-			out[pos++] = m._23;
-			out[pos++] = m._33;
-			out[pos++] = m._43;
-			return 12;
-		case TMat3:
-			var m : h3d.Matrix = v;
-			out[pos++] = m._11;
-			out[pos++] = m._21;
-			out[pos++] = m._31;
-			out[pos++] = 0;
-			out[pos++] = m._12;
-			out[pos++] = m._22;
-			out[pos++] = m._32;
-			out[pos++] = 0;
-			out[pos++] = m._13;
-			out[pos++] = m._23;
-			out[pos++] = m._33;
-			out[pos++] = 0;
-			return 12;
-		case TArray(TVec(4,VFloat), SConst(len)):
-			var v : Array<h3d.Vector4> = v;
-			for( i in 0...len ) {
-				var n = v[i];
-				if( n == null ) break;
-				out[pos++] = n.x;
-				out[pos++] = n.y;
-				out[pos++] = n.z;
-				out[pos++] = n.w;
-			}
-			return len * 4;
-		case TArray(TMat3x4, SConst(len)):
-			var v : Array<h3d.Matrix> = v;
-			for( i in 0...len ) {
-				var m = v[i];
-				if( m == null ) break;
-				out[pos++] = m._11;
-				out[pos++] = m._21;
-				out[pos++] = m._31;
-				out[pos++] = m._41;
-				out[pos++] = m._12;
-				out[pos++] = m._22;
-				out[pos++] = m._32;
-				out[pos++] = m._42;
-				out[pos++] = m._13;
-				out[pos++] = m._23;
-				out[pos++] = m._33;
-				out[pos++] = m._43;
-			}
-			return len * 12;
-		case TArray(TFloat, SConst(len)):
-			var v : Array<Float> = v;
-			var size = 0;
-			var count = v.length < len ? v.length : len;
-			for( i in 0...count )
-				out[pos++] = v[i];
-			return len;
-		case TArray(t, SConst(len)):
-			var v : Array<Dynamic> = v;
-			var size = 0;
-			for( i in 0...len ) {
-				var n = v[i];
-				if( n == null ) break;
-				size = fillRec(n, t, out, pos);
-				pos += size;
-			}
-			return len * size;
-		case TStruct(vl):
-			var tot = 0;
-			for( vv in vl )
-				tot += fillRec(Reflect.field(v, vv.name), vv.type, out, pos + tot);
-			return tot;
-		default:
-			throw "assert " + type;
-		}
-		return 0;
-	}
-
-	function shaderInfo( shaders : hxsl.ShaderList, path : String ) {
-		var name = path.split(".").pop();
-		while( shaders != null ) {
-			var inst = @:privateAccess shaders.s.instance;
-			for( v in inst.shader.vars )
-				if( v.name == name )
-					return shaders.s.toString();
-			shaders = shaders.next;
-		}
-		return "(not found)";
-	}
-
-	inline function getPtr( data : h3d.shader.Buffers.ShaderBufferData ) {
-		#if hl
-		return (hl.Bytes.getArray((cast data : Array<Single>)) : hl.BytesAccess<hl.F32>);
-		#else
-		return data;
-		#end
-	}
-
-	public inline function getParamValue( p : hxsl.RuntimeShader.AllocParam, shaders : hxsl.ShaderList, opt = false ) : Dynamic {
-		if( p.perObjectGlobal != null ) {
-			var v : Dynamic = globals.fastGet(p.perObjectGlobal.gid);
-			if( v == null ) throw "Missing global value " + p.perObjectGlobal.path+" for shader "+shaderInfo(shaders,p.perObjectGlobal.path);
-			if( p.type.match(TChannel(_)) )
-				return v.texture;
-			return v;
-		}
-		var si = shaders;
-		var n = p.instance;
-		while( --n > 0 ) si = si.next;
-		var v = si.s.getParamValue(p.index);
-		if( v == null && !opt ) throw "Missing param value " + si.s + "." + p.name;
-		return v;
-	}
-
-	public function fillGlobals( buf : h3d.shader.Buffers, s : hxsl.RuntimeShader ) {
-		inline function fill(buf:h3d.shader.Buffers.ShaderBuffers, s:hxsl.RuntimeShader.RuntimeShaderData) {
-			var g = s.globals;
-			var ptr = getPtr(buf.globals);
-			while( g != null ) {
-				var v = globals.fastGet(g.gid);
-				if( v == null )
-					throw "Missing global value " + g.path;
-				fillRec(v, g.type, ptr, g.pos);
-				g = g.next;
-			}
-		}
-		fill(buf.vertex, s.vertex);
-		fill(buf.fragment, s.fragment);
-	}
-
-	public function fillParams( buf : h3d.shader.Buffers, s : hxsl.RuntimeShader, shaders : hxsl.ShaderList ) {
-		var curInstance = -1;
-		var curInstanceValue = null;
-		inline function getInstance( index : Int ) {
-			if( curInstance == index )
-				return curInstanceValue;
-			var si = shaders;
-			curInstance = index;
-			while( --index > 0 ) si = si.next;
-			curInstanceValue = si.s;
-			return curInstanceValue;
-		}
-		inline function getParamValue( p : hxsl.RuntimeShader.AllocParam, shaders : hxsl.ShaderList, opt = false ) : Dynamic {
-			if( p.perObjectGlobal != null ) {
-				var v : Dynamic = globals.fastGet(p.perObjectGlobal.gid);
-				if( v == null ) throw "Missing global value " + p.perObjectGlobal.path+" for shader "+shaderInfo(shaders,p.perObjectGlobal.path);
-				if( p.type.match(TChannel(_)) )
-					return v.texture;
-				return v;
-			}
-			var v = getInstance(p.instance).getParamValue(p.index);
-			if( v == null && !opt ) throw "Missing param value " + shaders.s + "." + p.name;
-			return v;
-		}
-		inline function fill(buf:h3d.shader.Buffers.ShaderBuffers, s:hxsl.RuntimeShader.RuntimeShaderData) {
-			var p = s.params;
-			var ptr = getPtr(buf.params);
-			while( p != null ) {
-				var v : Dynamic;
-				if( p.perObjectGlobal == null ) {
-					if( p.type == TFloat ) {
-						var i = getInstance(p.instance);
-						ptr[p.pos] = i.getParamFloatValue(p.index);
-						p = p.next;
-						continue;
-					}
-					v = getInstance(p.instance).getParamValue(p.index);
-					if( v == null ) throw "Missing param value " + curInstanceValue + "." + p.name;
-				} else
-					v = getParamValue(p, shaders);
-				fillRec(v, p.type, ptr, p.pos);
-				p = p.next;
-			}
-			var tid = 0;
-			var p = s.textures;
-			while( p != null ) {
-				var t : Dynamic = getParamValue(p, shaders, !STRICT);
-				if( p.pos < 0 ) {
-					// is array !
-					var arr : Array<h3d.mat.Texture> = t;
-					for( i in 0...-p.pos )
-						buf.tex[tid++] = arr[i];
-				} else
-					buf.tex[tid++] = t;
-				p = p.next;
-			}
-			var p = s.buffers;
-			var bid = 0;
-			while( p != null ) {
-				var b : h3d.Buffer = getParamValue(p, shaders, !STRICT);
-				buf.buffers[bid++] = b;
-				p = p.next;
-			}
-		}
-		fill(buf.vertex, s.vertex);
-		fill(buf.fragment, s.fragment);
-	}
-
-	public function compileShaders( shaders : hxsl.ShaderList, mode : hxsl.RuntimeShader.LinkMode = Default ) {
+	public function compileShaders( globals : hxsl.Globals, shaders : hxsl.ShaderList, mode : hxsl.RuntimeShader.LinkMode = Default ) {
 		globals.resetChannels();
 		for( s in shaders ) s.updateConstants(globals);
 		currentOutput.next = shaders;

+ 3 - 5
h3d/pass/SpotShadowMap.hx

@@ -49,11 +49,6 @@ class SpotShadowMap extends Shadows {
 		return sshader.shadowMap;
 	}
 
-	override function setGlobals() {
-		super.setGlobals();
-		cameraViewProj = getShadowProj();
-	}
-
 	override function syncShader(texture) {
 		sshader.shadowMap = texture;
 		sshader.shadowMapChannel = format == h3d.mat.Texture.nativeFormat ? PackedFloat : R;
@@ -148,12 +143,15 @@ class SpotShadowMap extends Shadows {
 		var validBakedTexture = (staticTexture != null && staticTexture.width == texture.width);
 		if( mode == Mixed && !ctx.computingStatic && validBakedTexture ) {
 			var merge = ctx.textures.allocTarget("mergedSpotShadowMap", size, size, false, format);
+			var prev = @:privateAccess ctx.cameraViewProj;
+			@:privateAccess ctx.cameraViewProj = getShadowProj();
 			mergePass.shader.texA = texture;
 			mergePass.shader.texB = staticTexture;
 			ctx.engine.pushTarget(merge);
 			mergePass.render();
 			ctx.engine.popTarget();
 			texture = merge;
+			@:privateAccess ctx.cameraViewProj = prev;
 		}
 
 		syncShader(texture);

+ 1 - 1
h3d/scene/MeshBatch.hx

@@ -121,7 +121,7 @@ class MeshBatch extends MultiMaterial {
 
 				var manager = cast(ctx,h3d.pass.Default).manager;
 				var shaders = p.getShadersRec();
-				var rt = manager.compileShaders(shaders, Default);
+				var rt = manager.compileShaders(scene.ctx.globals, shaders, Default);
 				var shader = manager.shaderCache.makeBatchShader(rt, shaders, instancedParams);
 
 				var b = new BatchData();

+ 46 - 21
h3d/scene/RenderContext.hx

@@ -9,6 +9,7 @@ private class SharedGlobal {
 	}
 }
 
+@:build(hxsl.Macros.buildGlobals())
 class RenderContext extends h3d.impl.RenderContext {
 
 	public var camera : h3d.Camera;
@@ -17,7 +18,6 @@ class RenderContext extends h3d.impl.RenderContext {
 	public var pbrLightPass : h3d.mat.Pass;
 	public var computingStatic : Bool;
 
-	var sharedGlobals : Array<SharedGlobal>;
 	public var lightSystem : h3d.scene.LightSystem;
 	public var extraShaders : hxsl.ShaderList;
 	public var visibleFlag : Bool;
@@ -26,6 +26,20 @@ class RenderContext extends h3d.impl.RenderContext {
 	public var shaderBuffers : h3d.shader.Buffers;
 	public var cullingCollider : h3d.col.Collider;
 
+	@global("camera.view") var cameraView : h3d.Matrix;
+	@global("camera.zNear") var cameraNear : Float;
+	@global("camera.zFar") var cameraFar : Float;
+	@global("camera.proj") var cameraProj : h3d.Matrix;
+	@global("camera.position") var cameraPos : h3d.Vector;
+	@global("camera.projDiag") var cameraProjDiag : h3d.Vector4;
+	@global("camera.projFlip") var cameraProjFlip : Float;
+	@global("camera.viewProj") var cameraViewProj : h3d.Matrix;
+	@global("camera.inverseViewProj") var cameraInverseViewProj : h3d.Matrix;
+	@global("global.time") var globalTime : Float;
+	@global("global.pixelSize") var pixelSize : h3d.Vector;
+	@global("global.modelView") var globalModelView : h3d.Matrix;
+	@global("global.modelViewInverse") var globalModelViewInverse : h3d.Matrix;
+
 	var allocPool : h3d.pass.PassObject;
 	var allocFirst : h3d.pass.PassObject;
 	var cachedShaderList : Array<hxsl.ShaderList>;
@@ -33,12 +47,32 @@ class RenderContext extends h3d.impl.RenderContext {
 	var cachedPos : Int;
 	var passes : Array<h3d.pass.PassObject>;
 	var lights : Light;
-	var currentManager : h3d.pass.ShaderManager;
 
 	public function new() {
 		super();
 		cachedShaderList = [];
 		cachedPassObjects = [];
+		initGlobals();
+	}
+
+	public function setCamera( cam : h3d.Camera ) {
+		cameraView = cam.mcam;
+		cameraNear = cam.zNear;
+		cameraFar = cam.zFar;
+		cameraProj = cam.mproj;
+		cameraPos = cam.pos;
+		cameraProjDiag = new h3d.Vector4(cam.mproj._11,cam.mproj._22,cam.mproj._33,cam.mproj._44);
+		cameraViewProj = cam.m;
+		cameraInverseViewProj = camera.getInverseViewProj();
+	}
+
+	public function setupTarget() {
+		cameraProjFlip = engine.driver.hasFeature(BottomLeftCoords) && engine.getCurrentTarget() != null ? -1 : 1;
+	}
+
+	function getCurrentPixelSize() {
+		var t = engine.getCurrentTarget();
+		return new h3d.Vector(2 / (t == null ? engine.width : t.width), 2 / (t == null ? engine.height : t.height));
 	}
 
 	@:access(h3d.mat.Pass)
@@ -52,7 +86,6 @@ class RenderContext extends h3d.impl.RenderContext {
 	}
 
 	public function start() {
-		sharedGlobals = [];
 		lights = null;
 		drawPass = null;
 		passes = [];
@@ -61,6 +94,10 @@ class RenderContext extends h3d.impl.RenderContext {
 		visibleFlag = true;
 		time += elapsedTime;
 		frame++;
+		setCurrent();
+		globalTime = time;
+		pixelSize = getCurrentPixelSize();
+		setCamera(camera);
 	}
 
 	public inline function nextPass() {
@@ -68,25 +105,12 @@ class RenderContext extends h3d.impl.RenderContext {
 		drawPass = null;
 	}
 
-	public function getGlobal( name : String ) : Dynamic {
-		var id = hxsl.Globals.allocID(name);
-		for( g in sharedGlobals )
-			if( g.gid == id )
-				return g.value;
-		return null;
-	}
-
-	public inline function setGlobal( name : String, value : Dynamic ) {
-		setGlobalID(hxsl.Globals.allocID(name), value);
+	public inline function getGlobal(name) : Dynamic {
+		return globals.get(name);
 	}
 
-	public function setGlobalID( gid : Int, value : Dynamic ) {
-		for( g in sharedGlobals )
-			if( g.gid == gid ) {
-				g.value = value;
-				return;
-			}
-		sharedGlobals.push(new SharedGlobal(gid, value));
+	public inline function setGlobal(name,v:Dynamic) {
+		globals.set(name, v);
 	}
 
 	public function emitPass( pass : h3d.mat.Pass, obj : h3d.scene.Object ) @:privateAccess {
@@ -125,7 +149,7 @@ class RenderContext extends h3d.impl.RenderContext {
 	}
 
 	public function uploadParams() {
-		currentManager.fillParams(shaderBuffers, drawPass.shader, drawPass.shaders);
+		fillParams(shaderBuffers, drawPass.shader, drawPass.shaders);
 		engine.uploadShaderBuffers(shaderBuffers, Params);
 		engine.uploadShaderBuffers(shaderBuffers, Textures);
 		engine.uploadShaderBuffers(shaderBuffers, Buffers);
@@ -155,6 +179,7 @@ class RenderContext extends h3d.impl.RenderContext {
 		}
 		passes = [];
 		lights = null;
+		clearCurrent();
 	}
 
 }

+ 2 - 2
h3d/scene/fwd/Renderer.hx

@@ -20,7 +20,7 @@ class DepthPass extends h3d.pass.Default {
 		ctx.engine.clear(enableSky ? 0 : 0xFF0000, 1);
 		super.draw(passes, sort);
 		ctx.engine.popTarget();
-		ctx.setGlobalID(depthMapId, { texture : texture });
+		ctx.globals.fastSet(depthMapId, { texture : texture });
 	}
 
 }
@@ -44,7 +44,7 @@ class NormalPass extends h3d.pass.Default {
 		ctx.engine.clear(0x808080, 1);
 		super.draw(passes, sort);
 		ctx.engine.popTarget();
-		ctx.setGlobalID(normalMapId, texture);
+		ctx.globals.fastSet(normalMapId, texture);
 	}
 
 }

+ 1 - 11
hxsl/Macros.hx

@@ -447,7 +447,6 @@ class Macros {
 	public static function buildGlobals() {
 		var fields = Context.getBuildFields();
 		var globals = [];
-		var sets = [];
 		for( f in fields ) {
 			if( f.meta == null ) continue;
 			for( m in f.meta ) {
@@ -484,7 +483,7 @@ class Macros {
 						});
 						globals.push(macro $i{id} = new hxsl.Globals.GlobalSlot($v{ name }));
 						if( set != null )
-							sets.push(macro $i{f.name} = $set);
+							Context.error("Value ignored", set.pos);
 					default:
 					}
 			}
@@ -499,15 +498,6 @@ class Macros {
 			}),
 			pos : p,
 		});
-		fields.push({
-			name : "setGlobals",
-			kind : FFun({
-				ret : null,
-				expr : { expr : EBlock(sets), pos : p },
-				args : [],
-			}),
-			pos : p,
-		});
 		return fields;
 	}
 	#end