Browse Source

hxsl: added support for arrays of textures

Nicolas Cannasse 5 years ago
parent
commit
51d14f4419
5 changed files with 53 additions and 18 deletions
  1. 10 3
      h3d/impl/GlDriver.hx
  2. 8 1
      h3d/pass/ShaderManager.hx
  3. 13 2
      hxsl/Cache.hx
  4. 0 2
      hxsl/Checker.hx
  5. 22 10
      hxsl/Flatten.hx

+ 10 - 3
h3d/impl/GlDriver.hx

@@ -337,7 +337,12 @@ class GlDriver extends Driver {
 		var t = shader.textures;
 		while( t != null ) {
 			var tt = t.type;
-			if( tt.match(TChannel(_)) ) tt = TSampler2D;
+			var count = 1;
+			switch( tt ) {
+			case TChannel(_): tt = TSampler2D;
+			case TArray(t,SConst(n)): tt = t; count = n;
+			default:
+			}
 			if( tt != curT ) {
 				curT = tt;
 				name = switch( tt ) {
@@ -348,8 +353,10 @@ class GlDriver extends Driver {
 				}
 				index = 0;
 			}
-			s.textures.push({ u : gl.getUniformLocation(p.p, prefix+name+"["+index+"]"), t : curT, mode : mode });
-			index++;
+			for( i in 0...count ) {
+				s.textures.push({ u : gl.getUniformLocation(p.p, prefix+name+"["+index+"]"), t : curT, mode : mode });
+				index++;
+			}
 			t = t.next;
 		}
 		if( shader.bufferCount > 0 ) {

+ 8 - 1
h3d/pass/ShaderManager.hx

@@ -243,7 +243,14 @@ class ShaderManager {
 			var tid = 0;
 			var p = s.textures;
 			while( p != null ) {
-				buf.tex[tid++] = getParamValue(p, shaders, !STRICT);
+				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;

+ 13 - 2
hxsl/Cache.hx

@@ -369,6 +369,7 @@ class Cache {
 			switch( g.kind ) {
 			case Param:
 				var out = [];
+				var count = 0;
 				for( a in alloc ) {
 					if( a.v == null ) continue; // padding
 					var p = params.get(a.v.id);
@@ -376,16 +377,26 @@ class Cache {
 						var ap = new AllocParam(a.v.name, a.pos, -1, -1, a.v.type);
 						ap.perObjectGlobal = new AllocGlobal( -1, getPath(a.v), a.v.type);
 						out.push(ap);
+						count++;
 						continue;
 					}
-					out.push(new AllocParam(a.v.name, a.pos, p.instance, p.index, a.v.type));
+					var ap = new AllocParam(a.v.name, a.pos, p.instance, p.index, a.v.type);
+					switch( a.v.type ) {
+					case TArray(t,_) if( t.isSampler() ):
+						// hack to mark array of texture, see ShaderManager.fillParams
+						ap.pos = -a.size;
+						count += a.size;
+					default:
+						count++;
+					}
+					out.push(ap);
 				}
 				for( i in 0...out.length - 1 )
 					out[i].next = out[i + 1];
 				switch( g.type ) {
 				case TArray(t, _) if( t.isSampler() ):
 					textures.push({ t : t, all : out });
-					c.texturesCount += out.length;
+					c.texturesCount += count;
 				case TArray(TVec(4, VFloat), SConst(size)):
 					c.params = out[0];
 					c.paramsSize = size;

+ 0 - 2
hxsl/Checker.hx

@@ -820,8 +820,6 @@ class Checker {
 			case TStruct(_):
 				error("Array of structures are not allowed", pos);
 			default:
-				if( t.isSampler() )
-					error("Array of textures are not allowed, use Sampler2DArray instead", pos);
 			}
 			var s = switch( size ) {
 			case SConst(_): size;

+ 22 - 10
hxsl/Flatten.hx

@@ -84,8 +84,6 @@ class Flatten {
 			.concat(packTextures(prefix+"TexturesArray", allVars, TSampler2DArray));
 		packBuffers(allVars);
 		var funs = [for( f in s.funs ) mapFun(f, mapExpr)];
-		for( t in textures )
-			t.pos >>= 2;
 		return {
 			name : s.name,
 			vars : outVars,
@@ -117,6 +115,10 @@ class Flatten {
 				e
 			else {
 				switch( v.type ) {
+				case TArray(t, _) if( t.isSampler() ):
+					eindex = mapExpr(eindex);
+					var toInt = { e : TCall( { e : TGlobal(ToInt), t : TFun([]), p : vp }, [eindex]), t : TInt, p : vp };
+					access(a, t, vp, AOffset(a,1,toInt));
 				case TArray(t, _):
 					var stride = varSize(t, a.t);
 					if( stride == 0 || stride & 3 != 0 ) throw new Error("Dynamic access to an Array which size is not 4 components-aligned is not allowed", e.p);
@@ -252,11 +254,12 @@ class Flatten {
 	}
 
 	inline function readIndex( a : Alloc, index : Int, pos ) : TExpr {
-		return { e : TArray({ e : TVar(a.g), t : a.g.type, p : pos },mkInt((a.pos>>2)+index,pos)), t : TVec(4,a.t), p : pos }
+		var offs = a.t == null ? a.pos : a.pos >> 2;
+		return { e : TArray({ e : TVar(a.g), t : a.g.type, p : pos },mkInt(offs+index,pos)), t : TVec(4,a.t), p : pos }
 	}
 
 	inline function readOffset( a : Alloc, stride : Int, delta : TExpr, index : Int, pos ) : TExpr {
-		var index = (a.pos >> 2) + index;
+		var index = (a.t == null ? a.pos : a.pos >> 2) + index;
 		var offset : TExpr = index == 0 ? delta : { e : TBinop(OpAdd, delta, mkInt(index, pos)), t : TInt, p : pos };
 		return { e : TArray({ e : TVar(a.g), t : a.g.type, p : pos }, offset), t : TVec(4,a.t), p:pos };
 	}
@@ -353,20 +356,25 @@ class Flatten {
 			type : t,
 			kind : Param,
 		};
+		var pos = 0;
 		for( v in vars ) {
+			var count = 1;
 			if( v.type != t ) {
-				if( t == TSampler2D && v.type.match(TChannel(_)) ) {
-					// ok
-				} else
+				switch( v.type ) {
+				case TChannel(_) if( t == TSampler2D ):
+				case TArray(t2,SConst(n)) if( t2 == t ):
+					count = n;
+				default:
 					continue;
+				}
 			}
-			// use << 2 for readAccess purposes, then we will fix it before returning
-			var a = new Alloc(g, null, alloc.length << 2, 1);
+			var a = new Alloc(g, null, pos, count);
 			a.v = v;
 			varMap.set(v, a);
 			alloc.push(a);
+			pos += count;
 		}
-		g.type = TArray(t, SConst(alloc.length));
+		g.type = TArray(t, SConst(pos));
 		if( alloc.length > 0 ) {
 			outVars.push(g);
 			allocData.set(g, alloc);
@@ -404,6 +412,10 @@ class Flatten {
 		for( v in vars ) {
 			if( v.type.isSampler() || v.type.match(TBuffer(_)) )
 				continue;
+			switch( v.type ) {
+			case TArray(t,_) if( t.isSampler() ): continue;
+			default:
+			}
 			var size = varSize(v.type, t);
 			var best : Alloc = null;
 			for( a in alloc )