2
0
Эх сурвалжийг харах

changed Engine.setTarget with pushTarget/popTarget (easier to handle, optimized to minimize target changes)
removed Driver.reset (internal call by driver impl only)

Nicolas Cannasse 9 жил өмнө
parent
commit
6b9fab120b

+ 2 - 2
h2d/RenderContext.hx

@@ -98,7 +98,7 @@ class RenderContext extends h3d.impl.RenderContext {
 
 	public function pushTarget( t : h3d.mat.Texture, startX = 0, startY = 0, width = -1, height = -1 ) {
 		flush();
-		engine.setTarget(t);
+		engine.pushTarget(t);
 		initShaders(baseShaderList);
 		if( width < 0 ) width = t == null ? scene.width : t.width;
 		if( height < 0 ) height = t == null ? scene.height : t.height;
@@ -115,6 +115,7 @@ class RenderContext extends h3d.impl.RenderContext {
 		flush();
 		var tinf = targetsStack.pop();
 		if( tinf == null ) throw "Too many popTarget()";
+		engine.popTarget();
 
 		if( !restore ) return;
 
@@ -124,7 +125,6 @@ class RenderContext extends h3d.impl.RenderContext {
 		var startY = tinf == null ? 0 : tinf.y;
 		var width = tinf == null ? scene.width : tinf.w;
 		var height = tinf == null ? scene.height : tinf.h;
-		engine.setTarget(t);
 		initShaders(baseShaderList);
 		baseShader.halfPixelInverse.set(0.5 / (t == null ? engine.width : t.width), 0.5 / (t == null ? engine.height : t.height));
 		baseShader.viewport.set( -width * 0.5 - startX, -height * 0.5 - startY, 2 / width, -2 / height);

+ 4 - 2
h2d/Scene.hx

@@ -433,16 +433,18 @@ class Scene extends Layers implements h3d.IDrawable {
 		}
 		engine.begin();
 		engine.setRenderZone(target.x, target.y, target.width, target.height);
+
 		var tex = target.getTexture();
-		engine.setTarget(tex);
+		engine.pushTarget(tex);
 		var ow = width, oh = height, of = fixedSize;
 		setFixedSize(tex.width, tex.height);
 		render(engine);
+		engine.popTarget();
+
 		width = ow;
 		height = oh;
 		fixedSize = of;
 		posChanged = true;
-		engine.setTarget(null);
 		engine.setRenderZone();
 		engine.end();
 		return new Bitmap(target);

+ 2 - 1
h2d/filter/Bloom.hx

@@ -25,8 +25,9 @@ class Bloom extends Blur {
 		h3d.pass.Copy.run(t.getTexture(), dst);
 		var blurred = super.draw(ctx, t);
 		bloom.shader.texture = blurred.getTexture();
-		ctx.engine.setTarget(dst);
+		ctx.engine.pushTarget(dst);
 		bloom.render();
+		ctx.engine.popTarget();
 		return h2d.Tile.fromTexture(dst);
 	}
 

+ 2 - 1
h2d/filter/Displacement.hx

@@ -29,7 +29,7 @@ class Displacement extends Filter {
 
 	override function draw( ctx : RenderContext, t : h2d.Tile ) {
 		var out = ctx.textures.allocTarget("displacementOutput", ctx, t.width, t.height, false);
-		ctx.engine.setTarget(out);
+		ctx.engine.pushTarget(out);
 		var s = disp.shader;
 		s.texture = t.getTexture();
 		s.displacement.set(dispX / t.width, dispY / t.height);
@@ -37,6 +37,7 @@ class Displacement extends Filter {
 		s.normalPos.set(normalMap.u, normalMap.v);
 		s.normalScale.set(normalMap.u2 - normalMap.u, normalMap.v2 - normalMap.v);
 		disp.render();
+		ctx.engine.popTarget();
 		return h2d.Tile.fromTexture(out);
 	}
 

+ 2 - 1
h2d/filter/Shader.hx

@@ -25,10 +25,11 @@ class Shader< T:h3d.shader.ScreenShader > extends Filter {
 
 	override function draw( ctx : RenderContext, t : h2d.Tile ) {
 		var out = ctx.textures.allocTarget("shaderTmp", ctx, t.width, t.height, false);
-		ctx.engine.setTarget(out);
+		ctx.engine.pushTarget(out);
 		Reflect.setField(shader, textureParam + "__", t.getTexture());
 		if( nearest ) t.getTexture().filter = Nearest;
 		pass.render();
+		ctx.engine.popTarget();
 		return h2d.Tile.fromTexture(out);
 	}
 

+ 50 - 17
h3d/Engine.hx

@@ -1,6 +1,15 @@
 package h3d;
 import h3d.mat.Data;
 
+private class TargetTmp {
+	public var t : h3d.mat.Texture;
+	public var next : TargetTmp;
+	public function new(t, n) {
+		this.t = t;
+		this.next = n;
+	}
+}
+
 class Engine {
 
 	public var driver(default,null) : h3d.impl.Driver;
@@ -27,7 +36,11 @@ class Engine {
 	var lastTime : Float;
 	var antiAlias : Int;
 	var tmpVector = new h3d.Vector();
+
+	var targetTmp : TargetTmp;
+	var targetStack : TargetTmp;
 	var currentTarget : h3d.mat.Texture;
+	var needFlushTarget : Bool;
 
 	@:access(hxd.Stage)
 	public function new( hardware = true, aa = 0 ) {
@@ -80,6 +93,7 @@ class Engine {
 	}
 
 	public function selectShader( shader : hxsl.RuntimeShader ) {
+		flushTarget();
 		if( driver.selectShader(shader) )
 			shaderSwitches++;
 	}
@@ -95,6 +109,7 @@ class Engine {
 	function selectBuffer( buf : Buffer ) {
 		if( buf.isDisposed() )
 			return false;
+		flushTarget();
 		driver.selectBuffer(buf);
 		return true;
 	}
@@ -161,6 +176,7 @@ class Engine {
 	public function renderMultiBuffers( buffers : Buffer.BufferOffset, indexes : Indexes, startTri = 0, drawTri = -1 ) {
 		var maxTri = Std.int(indexes.count / 3);
 		if( maxTri <= 0 ) return;
+		flushTarget();
 		driver.selectMultiBuffers(buffers);
 		if( indexes.isDisposed() )
 			return;
@@ -244,45 +260,62 @@ class Engine {
 		drawTriangles = 0;
 		shaderSwitches = 0;
 		drawCalls = 0;
-		currentTarget = null;
+		targetStack = null;
+		needFlushTarget = currentTarget != null;
 		driver.begin(frameCount);
 		if( backgroundColor != null ) clear(backgroundColor, 1, 0);
 		return true;
 	}
 
-	function reset() {
-		driver.reset();
-	}
-
 	public function hasFeature(f) {
 		return driver.hasFeature(f);
 	}
 
 	public function end() {
 		driver.present();
-		reset();
 	}
 
-	public function getTarget() {
-		return currentTarget;
+	public function pushTarget( tex : h3d.mat.Texture ) {
+		var c = targetTmp;
+		if( c == null )
+			c = new TargetTmp(tex, targetStack);
+		else {
+			targetTmp = c.next;
+			c.t = tex;
+			c.next = targetStack;
+		}
+		targetStack = c;
+		needFlushTarget = currentTarget != tex;
 	}
 
-	/**
-	 * Setus a render target to do off screen rendering, might be costly on low end devices
-     * setTarget to null when you're finished rendering to it.
-	 */
-	public function setTarget( tex : h3d.mat.Texture ) {
-		var prev = currentTarget;
-		if( prev == tex )
-			return prev;
+	public function popTarget() {
+		var c = targetStack;
+		if( c == null )
+			throw "popTarget() with no matching pushTarget()";
+		targetStack = c.next;
+		var tex = targetStack == null ? null : targetStack.t;
+		needFlushTarget = currentTarget != tex;
+		// recycle
+		c.t = null;
+		c.next = targetTmp;
+		targetTmp = c;
+	}
+
+	inline function flushTarget() {
+		if( needFlushTarget ) doFlushTarget();
+	}
+
+	function doFlushTarget() {
+		var tex = targetStack == null ? null : targetStack.t;
 		currentTarget = tex;
 		driver.setRenderTarget(tex);
-		return prev;
+		needFlushTarget = false;
 	}
 
 	public function clear( ?color : Int, ?depth : Float, ?stencil : Int ) {
 		if( color != null )
 			tmpVector.setColor(color);
+		flushTarget();
 		driver.clear(color == null ? null : tmpVector, depth, stencil);
 	}
 

+ 0 - 3
h3d/impl/Driver.hx

@@ -95,9 +95,6 @@ class Driver {
 	public function captureRenderBuffer( pixels : hxd.Pixels ) {
 	}
 
-	public function reset() {
-	}
-
 	public function getDriverName( details : Bool ) {
 		return "Not available";
 	}

+ 0 - 4
h3d/impl/GlDriver.hx

@@ -121,10 +121,6 @@ class GlDriver extends Driver {
 		curAttribs = 0;
 		curMatBits = -1;
 		#end
-		reset();
-	}
-
-	override function reset() {
 		gl.useProgram(null);
 		curShader = null;
 		curBuffer = null;

+ 0 - 5
h3d/impl/LogDriver.hx

@@ -49,11 +49,6 @@ class LogDriver extends Driver {
 		d.captureRenderBuffer(pixels);
 	}
 
-	override function reset() {
-		log('Reset');
-		d.reset();
-	}
-
 	override function getDriverName( details : Bool ) {
 		return d.getDriverName(details);
 	}

+ 0 - 7
h3d/impl/ScnDriver.hx

@@ -94,11 +94,6 @@ class ScnDriver extends Driver {
 		d.captureRenderBuffer(pixels);
 	}
 
-	override function reset() {
-		ops.push(Reset);
-		d.reset();
-	}
-
 	override function getDriverName( details : Bool ) {
 		return d.getDriverName(details);
 	}
@@ -330,8 +325,6 @@ class ScnDriver extends Driver {
 			d.begin(++frame);
 		case Clear(color, depth, stencil):
 			d.clear(color,depth,stencil);
-		case Reset:
-			d.reset();
 		case Resize(w, h):
 			d.resize(w,h);
 		case SelectShader(id, data):

+ 1 - 1
h3d/impl/Stage3dDriver.hx

@@ -102,7 +102,7 @@ class Stage3dDriver extends Driver {
 		this.frame = frame;
 	}
 
-	override function reset() {
+	function reset() {
 		enableDraw = true;
 		curMatBits = -1;
 		curShader = null;

+ 3 - 2
h3d/mat/Texture.hx

@@ -183,10 +183,11 @@ class Texture {
 		#if js
 
 		var e = h3d.Engine.getCurrent();
-		var old = e.setTarget(this);
+		e.pushTarget(this);
+		@:privateAccess e.flushTarget();
 		var pixels = hxd.Pixels.alloc(width, height, RGBA);
 		e.driver.captureRenderBuffer(pixels);
-		e.setTarget(old);
+		e.popTarget();
 
 		#else
 		var e = h3d.Engine.getCurrent();

+ 4 - 3
h3d/pass/Blur.hx

@@ -100,17 +100,18 @@ class Blur extends ScreenFx<h3d.shader.Blur> {
 		for( i in 0...passes ) {
 			shader.texture = src;
 			shader.pixel.set(1 / src.width, 0);
-			engine.setTarget(tmp);
+			engine.pushTarget(tmp);
 			if( fullClearRequired ) engine.clear(0, 1, 0);
 			render();
+			engine.popTarget();
 
 			shader.texture = tmp;
 			shader.pixel.set(0, 1 / tmp.height);
-			engine.setTarget(output);
+			engine.pushTarget(output);
 			if( fullClearRequired ) engine.clear(0, 1, 0);
 			render();
+			engine.popTarget();
 		}
-		engine.setTarget(null);
 
 		if( alloc )
 			tmp.dispose();

+ 2 - 2
h3d/pass/ColorMatrix.hx

@@ -50,7 +50,7 @@ class ColorMatrix extends ScreenFx<ColorMatrixShader> {
 	inline function set_maskPower(p) return shader.maskPower = p;
 
 	public function apply( src : h3d.mat.Texture, out : h3d.mat.Texture, ?mask : h3d.mat.Texture, ?maskMatrix : h2d.col.Matrix ) {
-		var old = engine.setTarget(out);
+		engine.pushTarget(out);
 		shader.texture = src;
 		shader.useMask = mask != null;
 		if( mask != null ) {
@@ -64,7 +64,7 @@ class ColorMatrix extends ScreenFx<ColorMatrixShader> {
 			}
 		}
 		render();
-		engine.setTarget(old);
+		engine.popTarget();
 	}
 
 }

+ 2 - 2
h3d/pass/Copy.hx

@@ -20,12 +20,12 @@ class Copy extends ScreenFx<CopyShader> {
 
 	public function apply( from, to, ?blend : h3d.mat.BlendMode, ?uvDelta : h3d.Vector ) {
 		pass.setBlendMode(blend == null ? None : blend);
-		var prev = engine.setTarget(to);
+		engine.pushTarget(to);
 		shader.texture = from;
 		if( uvDelta == null ) shader.uvDelta.set(0, 0) else shader.uvDelta.set(uvDelta.x, uvDelta.y);
 		render();
 		shader.texture = null;
-		engine.setTarget(prev);
+		engine.popTarget();
 	}
 
 	static var inst : Copy;

+ 2 - 1
h3d/pass/Depth.hx

@@ -18,9 +18,10 @@ class Depth extends Default {
 
 	override function draw( passes ) {
 		var texture = tcache.allocTarget("depthMap", ctx, ctx.engine.width >> reduceSize, ctx.engine.height >> reduceSize);
-		ctx.engine.setTarget(texture);
+		ctx.engine.pushTarget(texture);
 		ctx.engine.clear(enableSky ? 0 : 0xFF0000, 1);
 		passes = super.draw(passes);
+		ctx.engine.popTarget();
 		ctx.setGlobalID(depthMapId, texture);
 		return passes;
 	}

+ 2 - 1
h3d/pass/Normal.hx

@@ -16,9 +16,10 @@ class Normal extends Default {
 
 	override function draw( passes ) {
 		var texture = tcache.allocTarget("normalMal", ctx, ctx.engine.width, ctx.engine.height);
-		ctx.engine.setTarget(texture);
+		ctx.engine.pushTarget(texture);
 		ctx.engine.clear(0x808080, 1);
 		passes = super.draw(passes);
+		ctx.engine.popTarget();
 		ctx.setGlobalID(normalMapId, texture);
 		return passes;
 	}

+ 2 - 1
h3d/pass/ShadowMap.hx

@@ -83,10 +83,11 @@ class ShadowMap extends Default {
 		lightCamera.pos.load(ct);
 		lightCamera.update();
 
-		ctx.engine.setTarget(texture);
+		ctx.engine.pushTarget(texture);
 		ctx.engine.clear(0xFFFFFF, 1, tcache.fullClearRequired ? 0 : null);
 		passes = super.draw(passes);
 		if( border != null ) border.render();
+		ctx.engine.popTarget();
 
 		if( blur.quality > 0 && blur.passes > 0 )
 			blur.apply(texture, tcache.allocTarget("tmpBlur", ctx, size, size, false), true);

+ 18 - 4
h3d/scene/Renderer.hx

@@ -23,6 +23,7 @@ class Renderer {
 	var allPasses : Array<{ name : String, p : h3d.pass.Base }>;
 	var ctx : RenderContext;
 	var tcache : h3d.impl.TextureCache;
+	var hasSetTarget = false;
 
 	public function new() {
 		passes = new SMap();
@@ -122,8 +123,18 @@ class Renderer {
 		ctx.engine.clear(color, depth, stencil);
 	}
 
+	inline function pushTarget( tex ) {
+		ctx.engine.pushTarget(tex);
+	}
+
 	inline function setTarget( tex ) {
-		ctx.engine.setTarget(tex);
+		if( hasSetTarget ) ctx.engine.popTarget();
+		ctx.engine.pushTarget(tex);
+		hasSetTarget = true;
+	}
+
+	inline function popTarget() {
+		ctx.engine.popTarget();
 	}
 
 	function get( name : String ) {
@@ -148,10 +159,8 @@ class Renderer {
 				var passes = pdata == null ? null : pdata.passes;
 				if( p.name == "alpha" )
 					passes = depthSort(passes);
-				if( p.name == "default" ) {
-					setTarget(null);
+				if( p.name == "default" )
 					passes = depthSort(passes, true);
-				}
 				passes = p.p.draw(passes);
 				if( pdata != null ) {
 					pdata.passes = passes;
@@ -163,12 +172,17 @@ class Renderer {
 
 	public function process( ctx : RenderContext, passes : Array<PassGroup> ) {
 		this.ctx = ctx;
+		hasSetTarget = false;
 		// alloc passes
 		for( p in passes ) {
 			getPass(p.name).setContext(ctx);
 			passGroups.set(p.name, p);
 		}
 		render();
+		if( hasSetTarget ) {
+			ctx.engine.popTarget();
+			hasSetTarget = false;
+		}
 		for( p in passes )
 			passGroups.set(p.name, null);
 	}

+ 0 - 1
hxd/fmt/scn/Data.hx

@@ -6,7 +6,6 @@ enum Operation {
 	Log( str : String );
 	Begin;
 	Clear( ?color : h3d.Vector, ?depth : Float, ?stencil : Int );
-	Reset;
 	Resize( width : Int, height : Int );
 	SelectShader( id : Int, ?data : Serialized<hxsl.RuntimeShader> );
 	Material( bits : Int );

+ 1 - 1
hxd/fmt/scn/Writer.hx

@@ -18,7 +18,7 @@ class Writer {
 			case Log(str):
 				out.addInt32(str.length);
 				out.addString(str);
-			case Begin, Reset, Present:
+			case Begin, Present:
 			case Clear(color, depth, stencil):
 				out.addByte((color == null ? 0 : 1) | (depth == null ? 0 : 2) | (stencil == null ? 0 : 4));
 				if( color != null ) {