Jelajahi Sumber

handle unique names in GlslOut

Nicolas Cannasse 11 tahun lalu
induk
melakukan
e5c770a637
3 mengubah file dengan 126 tambahan dan 98 penghapusan
  1. 39 38
      h3d/impl/GlDriver.hx
  2. 70 48
      hxsl/GlslOut.hx
  3. 17 12
      hxsl/Printer.hx

+ 39 - 38
h3d/impl/GlDriver.hx

@@ -50,14 +50,14 @@ class GlDriver extends Driver {
 	static var gl = GL;
 	var fixMult : Bool;
 	#end
-	
+
 	var curAttribs : Int;
 	var curProgram : CompiledProgram;
 	var curMatBits : Int;
 	var programs : Map<Int, CompiledProgram>;
 	var hasTargetFlip : Bool;
 	var frame : Int;
-	
+
 	public function new() {
 		#if js
 		canvas = @:privateAccess hxd.Stage.getCanvas();
@@ -77,26 +77,26 @@ class GlDriver extends Driver {
 		curMatBits = -1;
 		selectMaterialBits(0);
 	}
-	
+
 	override function begin(frame) {
 		this.frame = frame;
 		reset();
 	}
-	
+
 	override function reset() {
 		gl.useProgram(null);
 		curProgram = null;
 		hasTargetFlip = false;
 	}
-	
+
 	override function getShaderInputNames() {
 		return curProgram.attribNames;
 	}
-	
-	function compileShader( shader : hxsl.RuntimeShader.RuntimeShaderData ) {
+
+	function compileShader( glout : hxsl.GlslOut, shader : hxsl.RuntimeShader.RuntimeShaderData ) {
 		var type = shader.vertex ? GL.VERTEX_SHADER : GL.FRAGMENT_SHADER;
 		var s = gl.createShader(type);
-		var code = hxsl.GlslOut.toGlsl(shader.data);
+		var code = glout.run(shader.data);
 		gl.shaderSource(s, code);
 		gl.compileShader(s);
 		if( gl.getShaderParameter(s, GL.COMPILE_STATUS) != cast 1 ) {
@@ -107,20 +107,21 @@ class GlDriver extends Driver {
 		}
 		return new CompiledShader(s,shader.vertex);
 	}
-	
+
 	function initShader( p : CompiledProgram, s : CompiledShader, shader : hxsl.RuntimeShader.RuntimeShaderData ) {
 		var prefix = s.vertex ? "vertex" : "fragment";
 		s.globals = gl.getUniformLocation(p.p, prefix + "Globals");
 		s.params = gl.getUniformLocation(p.p, prefix + "Params");
 		s.textures = [for( i in 0...shader.textures.length ) gl.getUniformLocation(p.p, prefix + "Textures[" + i + "]")];
 	}
-	
+
 	override function selectShader( shader : hxsl.RuntimeShader ) {
 		var p = programs.get(shader.id);
 		if( p == null ) {
 			p = new CompiledProgram();
-			p.vertex = compileShader(shader.vertex);
-			p.fragment = compileShader(shader.fragment);
+			var glout = new hxsl.GlslOut();
+			p.vertex = compileShader(glout,shader.vertex);
+			p.fragment = compileShader(glout,shader.fragment);
 			p.p = gl.createProgram();
 			gl.attachShader(p.p, p.vertex.s);
 			gl.attachShader(p.p, p.fragment.s);
@@ -144,7 +145,7 @@ class GlDriver extends Driver {
 					case TFloat: 1;
 					default: throw "assert " + v.type;
 					}
-					p.attribs.push( { offset : p.stride, index : gl.getAttribLocation(p.p, v.name), size:size, type:t } );
+					p.attribs.push( { offset : p.stride, index : gl.getAttribLocation(p.p, glout.varNames.get(v.id)), size:size, type:t } );
 					p.attribNames.push(v.name);
 					p.stride += size;
 				default:
@@ -162,12 +163,12 @@ class GlDriver extends Driver {
 		curProgram = p;
 		return true;
 	}
-	
+
 	override function uploadShaderBuffers( buf : h3d.shader.Buffers, which : h3d.shader.Buffers.BufferKind ) {
 		uploadBuffer(curProgram.vertex, buf.vertex, which);
 		uploadBuffer(curProgram.fragment, buf.fragment, which);
 	}
-	
+
 	function uploadBuffer( s : CompiledShader, buf : h3d.shader.Buffers.ShaderBuffers, which : h3d.shader.Buffers.BufferKind ) {
 		switch( which ) {
 		case Globals:
@@ -184,10 +185,10 @@ class GlDriver extends Driver {
 					t.realloc();
 				}
 				t.lastFrame = frame;
-				
+
 				gl.activeTexture(GL.TEXTURE0 + i);
 				gl.uniform1i(s.textures[i], i);
-				
+
 				gl.bindTexture(GL.TEXTURE_2D, t.t.t);
 				var flags = TFILTERS[Type.enumIndex(t.mipMap)][Type.enumIndex(t.filter)];
 				gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, flags[0]);
@@ -198,12 +199,12 @@ class GlDriver extends Driver {
 			}
 		}
 	}
-	
+
 	override function selectMaterial( pass : Pass ) {
 		selectMaterialBits(@:privateAccess pass.bits);
 		// TODO : Blend Op value sync
 	}
-	
+
 	function selectMaterialBits( bits : Int ) {
 		if( hasTargetFlip ) {
 			// switch culling font/back
@@ -265,13 +266,13 @@ class GlDriver extends Driver {
 		}
 		curMatBits = bits;
 	}
-	
+
 	override function clear( r : Float, g : Float, b : Float, a : Float ) {
 		gl.clearColor(r, g, b, a);
 		gl.clearDepth(1);
 		gl.clear(GL.COLOR_BUFFER_BIT|GL.DEPTH_BUFFER_BIT);
 	}
-	
+
 	override function resize(width, height) {
 		#if js
 		// prevent infinite grow if pixelRatio != 1
@@ -286,7 +287,7 @@ class GlDriver extends Driver {
 		#end
 		gl.viewport(0, 0, width, height);
 	}
-	
+
 	override function allocTexture( t : h3d.mat.Texture ) : Texture {
 		var tt = gl.createTexture();
 		var tt : Texture = { t : tt, width : t.width, height : t.height, fmt : GL.UNSIGNED_BYTE };
@@ -321,7 +322,7 @@ class GlDriver extends Driver {
 		gl.bindTexture(GL.TEXTURE_2D, null);
 		return tt;
 	}
-	
+
 	override function allocVertex( m : ManagedBuffer ) : VertexBuffer {
 		var b = gl.createBuffer();
 		#if js
@@ -337,7 +338,7 @@ class GlDriver extends Driver {
 		#end
 		return { b : b, stride : m.stride };
 	}
-	
+
 	override function allocIndexes( count : Int ) : IndexBuffer {
 		var b = gl.createBuffer();
 		#if js
@@ -362,7 +363,7 @@ class GlDriver extends Driver {
 	override function disposeIndexes( i : IndexBuffer ) {
 		gl.deleteBuffer(i);
 	}
-	
+
 	override function disposeVertex( v : VertexBuffer ) {
 		gl.deleteBuffer(v.b);
 	}
@@ -383,7 +384,7 @@ class GlDriver extends Driver {
 		if( t.flags.has(MipMapped) ) gl.generateMipmap(GL.TEXTURE_2D);
 		gl.bindTexture(GL.TEXTURE_2D, null);
 	}
-	
+
 	override function uploadVertexBuffer( v : VertexBuffer, startVertex : Int, vertexCount : Int, buf : hxd.FloatBuffer, bufPos : Int ) {
 		var stride : Int = v.stride;
 		var buf = new Float32Array(buf.getNative());
@@ -417,7 +418,7 @@ class GlDriver extends Driver {
 		gl.bufferSubData(GL.ELEMENT_ARRAY_BUFFER, startIndice * 2, sub);
 		gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, null);
 	}
-	
+
 	override function selectBuffer( v : VertexBuffer ) {
 		var stride : Int = v.stride;
 		if( stride < curProgram.stride )
@@ -426,7 +427,7 @@ class GlDriver extends Driver {
 		for( a in curProgram.attribs )
 			gl.vertexAttribPointer(a.index, a.size, a.type, false, stride * 4, a.offset * 4);
 	}
-	
+
 	override function selectMultiBuffers( buffers : Buffer.BufferOffset ) {
 		for( a in curProgram.attribs ) {
 			gl.bindBuffer(GL.ARRAY_BUFFER, @:privateAccess buffers.buffer.buffer.vbuf.b);
@@ -434,13 +435,13 @@ class GlDriver extends Driver {
 			buffers = buffers.next;
 		}
 	}
-	
+
 	override function draw( ibuf : IndexBuffer, startIndex : Int, ntriangles : Int ) {
 		gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, ibuf);
 		gl.drawElements(GL.TRIANGLES, ntriangles * 3, GL.UNSIGNED_SHORT, startIndex * 2);
 		gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, null);
 	}
-	
+
 	override function present() {
 		gl.finish();
 	}
@@ -448,7 +449,7 @@ class GlDriver extends Driver {
 	override function isDisposed() {
 		return gl.isContextLost();
 	}
-	
+
 	override function setRenderTarget( tex : h3d.mat.Texture, clearColor : Int ) {
 		if( tex == null ) {
 			gl.bindFramebuffer(GL.FRAMEBUFFER, null);
@@ -479,7 +480,7 @@ class GlDriver extends Driver {
 		haxe.Timer.delay(onCreate.bind(false), 1);
 		#end
 	}
-	
+
 	override function hasFeature( f : Feature ) : Bool {
 		return switch( f ) {
 		case StandardDerivatives:
@@ -488,25 +489,25 @@ class GlDriver extends Driver {
 			gl.getExtension('OES_texture_float') != null && gl.getExtension('OES_texture_float_linear') != null;
 		}
 	}
-	
+
 	static var TFILTERS = [
 		[[GL.NEAREST,GL.NEAREST],[GL.LINEAR,GL.LINEAR]],
 		[[GL.NEAREST,GL.NEAREST_MIPMAP_NEAREST],[GL.LINEAR,GL.LINEAR_MIPMAP_NEAREST]],
 		[[GL.NEAREST,GL.NEAREST_MIPMAP_LINEAR],[GL.LINEAR,GL.LINEAR_MIPMAP_LINEAR]],
 	];
-	
+
 	static var TWRAP = [
 		GL.CLAMP_TO_EDGE,
 		GL.REPEAT,
 	];
-	
+
 	static var FACES = [
 		0,
 		GL.FRONT, // front/back reversed wrt stage3d
 		GL.BACK,
 		GL.FRONT_AND_BACK,
 	];
-	
+
 	static var BLEND = [
 		GL.ONE,
 		GL.ZERO,
@@ -524,7 +525,7 @@ class GlDriver extends Driver {
 		GL.ONE_MINUS_CONSTANT_ALPHA,
 		GL.SRC_ALPHA_SATURATE,
 	];
-	
+
 	static var COMPARE = [
 		GL.ALWAYS,
 		GL.NEVER,
@@ -535,7 +536,7 @@ class GlDriver extends Driver {
 		GL.LESS,
 		GL.LEQUAL,
 	];
-	
+
 	static var OP = [
 		GL.FUNC_ADD,
 		GL.FUNC_SUBTRACT,

+ 70 - 48
hxsl/GlslOut.hx

@@ -2,45 +2,55 @@ package hxsl;
 import hxsl.Ast;
 
 class GlslOut {
-	
+
+	static var KWD_LIST = [
+		"input", "output", "discard",
+		"dvec2", "dvec3", "dvec4",
+	];
+	static var KWDS = [for( k in KWD_LIST ) k => true];
+	static var GLOBALS = {
+		var m = new Map();
+		for( g in hxsl.Ast.TGlobal.createAll() ) {
+			var n = "" + g;
+			n = n.charAt(0).toLowerCase() + n.substr(1);
+			m.set(g, n);
+		}
+		m.set(ToInt, "int");
+		m.set(ToFloat, "float");
+		m.set(ToBool, "bool");
+		for( g in m )
+			KWDS.set(g, true);
+		m;
+	};
 	static var MAT34 = "struct mat3x4 { vec4 a; vec4 b; vec4 c; };";
 
 	var buf : StringBuf;
-	var keywords : Map<String,Bool>;
 	var exprValues : Array<String>;
 	var locals : Array<TVar>;
 	var decls : Array<String>;
-	var globalNames : Map<TGlobal,String>;
-	
+	var isVertex : Bool;
+	var allNames : Map<String, Int>;
+	public var varNames : Map<Int,String>;
+
 	public function new() {
-		keywords = [ "input" => true, "output" => true, "discard" => true ];
-		for( i in 2...5 )
-			keywords.set("dvec" + i, true);
-		globalNames = new Map();
-		for( g in hxsl.Ast.TGlobal.createAll() ) {
-			var n = "" + g;
-			n = n.charAt(0).toLowerCase() + n.substr(1);
-			globalNames.set(g, n);
-		}
-		globalNames.set(ToInt, "int");
-		globalNames.set(ToFloat, "float");
-		globalNames.set(ToBool, "bool");
+		varNames = new Map();
+		allNames = new Map();
 	}
-	
+
 	inline function add( v : Dynamic ) {
 		buf.add(v);
 	}
-	
-	function ident( i : String ) {
-		add(keywords.exists(i) ? "_" + i : i);
+
+	inline function ident( v : TVar ) {
+		add(varName(v));
 	}
-	
+
 	function decl( s : String ) {
 		for( d in decls )
 			if( d == s ) return;
 		decls.push(s);
 	}
-	
+
 	function addType( t : Type ) {
 		switch( t ) {
 		case TVoid:
@@ -89,14 +99,14 @@ class GlslOut {
 			add("[");
 			switch( size ) {
 			case SVar(v):
-				ident(v.name);
+				ident(v);
 			case SConst(v):
 				add(v);
 			}
 			add("]");
 		}
 	}
-	
+
 	function addVar( v : TVar ) {
 		switch( v.type ) {
 		case TArray(t, size):
@@ -106,17 +116,17 @@ class GlslOut {
 			v.type = old;
 			add("[");
 			switch( size ) {
-			case SVar(v): ident(v.name);
+			case SVar(v): ident(v);
 			case SConst(n): add(n);
 			}
 			add("]");
 		default:
 			addType(v.type);
 			add(" ");
-			ident(v.name);
+			ident(v);
 		}
 	}
-	
+
 	function addValue( e : TExpr, tabs : String ) {
 		switch( e.e ) {
 		case TBlock(el):
@@ -144,7 +154,7 @@ class GlslOut {
 			addExpr(e, tabs);
 		}
 	}
-	
+
 	function addExpr( e : TExpr, tabs : String ) {
 		switch( e.e ) {
 		case TConst(c):
@@ -160,7 +170,7 @@ class GlslOut {
 			case CBool(b): add(b);
 			}
 		case TVar(v):
-			ident(v.name);
+			ident(v);
 		case TGlobal(g):
 			switch( g ) {
 			case Mat3x4:
@@ -174,7 +184,7 @@ class GlslOut {
 				decl("float unpack( vec4 color ) { return dot(color,vec4(1., 1. / 255., 1. / (255. * 255.), 1. / (255. * 255. * 255.))); }");
 			default:
 			}
-			add(globalNames.get(g));
+			add(GLOBALS.get(g));
 		case TParenthesis(e):
 			add("(");
 			addValue(e,tabs);
@@ -216,7 +226,7 @@ class GlslOut {
 		case TVarDecl(v, init):
 			locals.push(v);
 			if( init != null ) {
-				ident(v.name);
+				ident(v);
 				add(" = ");
 				addValue(init, tabs);
 			} else {
@@ -285,7 +295,28 @@ class GlslOut {
 			add("]");
 		}
 	}
-	
+
+	function varName( v : TVar ) {
+		if( v.kind == Output )
+			return isVertex ? "gl_Position" : "gl_FragColor";
+		var n = varNames.get(v.id);
+		if( n != null )
+			return n;
+		n = v.name;
+		if( KWDS.exists(n) )
+			n = "_" + n;
+		if( allNames.exists(n) ) {
+			var k = 2;
+			n += "_";
+			while( allNames.exists(n + k) )
+				k++;
+			n += k;
+		}
+		varNames.set(v.id, n);
+		allNames.set(n, v.id);
+		return n;
+	}
+
 	public function run( s : ShaderData ) {
 		locals = [];
 		decls = [];
@@ -295,7 +326,8 @@ class GlslOut {
 
 		if( s.funs.length != 1 ) throw "assert";
 		var f = s.funs[0];
-		
+		isVertex = f.kind == Vertex;
+
 		for( v in s.vars ) {
 			switch( v.kind ) {
 			case Param, Global:
@@ -304,31 +336,21 @@ class GlslOut {
 				add("attribute ");
 			case Var:
 				add("varying ");
-			case Function: continue;
-			case Output:
-				switch( f.kind ) {
-				case Vertex:
-					v.name = "gl_Position";
-				case Fragment:
-					v.name = "gl_FragColor";
-				default:
-					throw "assert";
-				}
-				continue;
+			case Function, Output: continue;
 			case Local:
 			}
 			addVar(v);
 			add(";\n");
 		}
 		add("\n");
-		
+
 		var tmp = buf;
 		buf = new StringBuf();
 		add("void main(void) ");
 		addExpr(f.expr, "");
 		exprValues.push(buf.toString());
 		buf = tmp;
-		
+
 		for( v in locals ) {
 			addVar(v);
 			add(";\n");
@@ -343,9 +365,9 @@ class GlslOut {
 		buf = null;
 		return decls.join("\n");
 	}
-	
+
 	public static function toGlsl( s : ShaderData ) {
 		return new GlslOut().run(s);
 	}
-	
+
 }

+ 17 - 12
hxsl/Printer.hx

@@ -2,18 +2,18 @@ package hxsl;
 using hxsl.Ast;
 
 class Printer {
-	
+
 	var buffer : StringBuf;
 	var varId : Bool;
 
 	public function new(varId = false) {
 		this.varId = varId;
 	}
-	
+
 	inline function add(v:Dynamic) {
 		buffer.add(v);
 	}
-	
+
 	public function shaderString( s : ShaderData ) {
 		buffer = new StringBuf();
 		for( v in s.vars ) {
@@ -28,7 +28,7 @@ class Printer {
 		}
 		return buffer.toString();
 	}
-	
+
 	public function varString( v : TVar ) {
 		buffer = new StringBuf();
 		addVar(v, null);
@@ -47,7 +47,7 @@ class Printer {
 		return buffer.toString();
 	}
 
-	function addVar( v : TVar, defKind : VarKind, tabs = "" ) {
+	function addVar( v : TVar, defKind : VarKind, tabs = "", ?parent ) {
 		if( v.qualifiers != null ) {
 			for( q in v.qualifiers )
 				add("@" + (switch( q ) {
@@ -75,21 +75,26 @@ class Printer {
 			case Output:
 				add("@output ");
 			}
-		add("var " + v.name + (varId?"@" + v.id:"") + " : ");
+		add("var ");
+		if( v.parent == parent )
+			add(v.name + (varId?"@" + v.id:""));
+		else
+			addVarName(v);
+		add(" : ");
 		switch( v.type ) {
 		case TStruct(vl):
 			add("{");
 			var first = true;
 			for( v in vl ) {
 				if( first ) first = false else add(", ");
-				addVar(v,v.kind);
+				addVar(v,v.kind,tabs,v);
 			}
 			add("}");
 		default:
 			add(v.type.toString());
 		}
 	}
-	
+
 	function addFun( f : TFunction ) {
 		add("function " + f.ref.name + "(");
 		var first = true;
@@ -105,7 +110,7 @@ class Printer {
 		add(") : "+f.ret.toString()+" ");
 		addExpr(f.expr,"");
 	}
-	
+
 	function addVarName( v : TVar ) {
 		if( v.parent != null ) {
 			addVarName(v.parent);
@@ -115,7 +120,7 @@ class Printer {
 		if( varId )
 			add("@" + v.id);
 	}
-	
+
 	function addExpr( e : TExpr, tabs : String ) : Void {
 		switch( e.e ) {
 		case TVar(v):
@@ -220,7 +225,7 @@ class Printer {
 			add("]");
 		}
 	}
-	
+
 	public static function opStr( op : Ast.Binop ) {
 		return switch(op) {
 		case OpAdd:"+";
@@ -256,5 +261,5 @@ class Printer {
 	public static function shaderToString( s : ShaderData, varId = false ) {
 		return new Printer(varId).shaderString(s);
 	}
-	
+
 }