ソースを参照

Implement GLES3+ and HXSL texelFetch (#576)

Fix ivec and bvec generation.
Pavel Alexandrov 6 年 前
コミット
fa25f3b4f2
5 ファイル変更90 行追加1 行削除
  1. 4 0
      hxsl/Ast.hx
  2. 32 1
      hxsl/Checker.hx
  3. 6 0
      hxsl/Dce.hx
  4. 20 0
      hxsl/GlslOut.hx
  5. 28 0
      hxsl/HlslOut.hx

+ 4 - 0
hxsl/Ast.hx

@@ -202,6 +202,8 @@ enum TGlobal {
 	//All;
 	Texture;
 	TextureLod;
+	Texel;
+	TexelLod;
 	// ...other texture* operations
 	// constructors
 	ToInt;
@@ -235,6 +237,8 @@ enum TGlobal {
 	// debug / internal
 	ChannelRead;
 	ChannelReadLod;
+	ChannelFetch;
+	ChannelFetchLod;
 	Trace;
 	// instancing
 	VertexID;

+ 32 - 1
hxsl/Checker.hx

@@ -22,6 +22,9 @@ class Checker {
 	static var vec2 = TVec(2, VFloat);
 	static var vec3 = TVec(3, VFloat);
 	static var vec4 = TVec(4, VFloat);
+	static var ivec2 = TVec(2, VInt);
+	static var ivec3 = TVec(3, VInt);
+	static var ivec4 = TVec(4, VInt);
 
 	var vars : Map<String,TVar>;
 	var globals : Map<String,{ g : TGlobal, t : Type }>;
@@ -74,6 +77,16 @@ class Checker {
 					{ args : [ { name : "tex", type : TSamplerCube }, { name : "normal", type : vec3 }, { name : "lod", type : TFloat } ], ret : vec4 },
 					{ args : [ { name : "tex", type : TSampler2DArray }, { name : "uv", type : vec3 }, { name : "lod", type : TFloat } ], ret : vec4 },
 				];
+			case Texel:
+				[
+					{ args : [ { name: "tex", type: TSampler2D }, { name: "pos", type: ivec2 } ], ret: vec4 },
+					{ args : [ { name: "tex", type: TSampler2DArray }, { name: "pos", type: ivec3 } ], ret: vec4 }
+				];
+			case TexelLod:
+				[
+					{ args : [ { name: "tex", type: TSampler2D }, { name: "pos", type: ivec2 }, { name: "lod", type: TInt } ], ret: vec4 },
+					{ args : [ { name: "tex", type: TSampler2DArray }, { name: "pos", type: ivec3 }, { name: "lod", type: TInt } ], ret: vec4 }
+				];
 			case ToInt:
 				[for( t in baseType ) { args : [ { name : "value", type : t } ], ret : TInt } ];
 			case ToFloat:
@@ -136,6 +149,20 @@ class Checker {
 					{ args : [ { name : "channel", type : TChannel(3) }, { name : "uv", type : vec2 }, { name : "lod", type : TFloat } ], ret : vec3 },
 					{ args : [ { name : "channel", type : TChannel(4) }, { name : "uv", type : vec2 }, { name : "lod", type : TFloat } ], ret : vec4 },
 				];
+			case ChannelFetch:
+				[
+					{ args : [ { name : "channel", type : TChannel(1) }, { name : "pos", type : ivec2 } ], ret : TFloat },
+					{ args : [ { name : "channel", type : TChannel(2) }, { name : "pos", type : ivec2 } ], ret : vec2 },
+					{ args : [ { name : "channel", type : TChannel(3) }, { name : "pos", type : ivec2 } ], ret : vec3 },
+					{ args : [ { name : "channel", type : TChannel(4) }, { name : "pos", type : ivec2 } ], ret : vec4 },
+				];
+			case ChannelFetchLod:
+				[
+					{ args : [ { name : "channel", type : TChannel(1) }, { name : "pos", type : ivec2 }, { name : "lod", type : TInt } ], ret : TFloat },
+					{ args : [ { name : "channel", type : TChannel(2) }, { name : "pos", type : ivec2 }, { name : "lod", type : TInt } ], ret : vec2 },
+					{ args : [ { name : "channel", type : TChannel(3) }, { name : "pos", type : ivec2 }, { name : "lod", type : TInt } ], ret : vec3 },
+					{ args : [ { name : "channel", type : TChannel(4) }, { name : "pos", type : ivec2 }, { name : "lod", type : TInt } ], ret : vec4 },
+				];
 			case ScreenToUv:
 				[{ args : [{ name : "screenPos", type : vec2 }], ret : vec2 }];
 			case UvToScreen:
@@ -688,7 +715,7 @@ class Checker {
 		switch( e.e ) {
 		case TConst(_):
 		case TParenthesis(e): checkConst(e);
-		case TCall({ e : TGlobal(Vec2 | Vec3 | Vec4) }, args):
+		case TCall({ e : TGlobal(Vec2 | Vec3 | Vec4 | IVec2 | IVec3 | IVec4) }, args):
 			for( a in args ) checkConst(a);
 		default:
 			error("This expression should be constant", e.p);
@@ -847,6 +874,10 @@ class Checker {
 			case ["get", TChannel(_)]: ChannelRead;
 			case ["getLod", TSampler2D|TSampler2DArray|TSamplerCube]: TextureLod;
 			case ["getLod", TChannel(_)]: ChannelReadLod;
+			case ["fetch", TSampler2D|TSampler2DArray]: Texel;
+			case ["fetch", TChannel(_)]: ChannelFetch;
+			case ["fetchLod", TSampler2D|TSampler2DArray]: TexelLod;
+			case ["fetchLod", TChannel(_)]: ChannelFetchLod;
 			default: null;
 			}
 			if( gl != null ) {

+ 6 - 0
hxsl/Dce.hx

@@ -232,6 +232,12 @@ class Dce {
 		case TCall({ e : TGlobal(ChannelReadLod) }, [_, uv, lod, { e : TConst(CInt(cid)) }]):
 			var c = channelVars[cid];
 			return { e : TCall({ e : TGlobal(TextureLod), p : e.p, t : TVoid }, [{ e : TVar(c), t : c.type, p : e.p }, mapExpr(uv,true), mapExpr(lod,true)]), t : TVoid, p : e.p };
+		case TCall({ e : TGlobal(ChannelFetch) }, [_, pos, { e : TConst(CInt(cid)) }]):
+			var c = channelVars[cid];
+			return { e : TCall({ e : TGlobal(Texel), p : e.p, t : TVoid }, [{ e : TVar(c), t : c.type, p : e.p }, mapExpr(pos,true)]), t : TVoid, p : e.p };
+		case TCall({ e : TGlobal(ChannelFetchLod) }, [_, pos, lod, { e : TConst(CInt(cid)) }]):
+			var c = channelVars[cid];
+			return { e : TCall({ e : TGlobal(Texel), p : e.p, t : TVoid }, [{ e : TVar(c), t : c.type, p : e.p }, mapExpr(pos,true), mapExpr(lod,true)]), t : TVoid, p : e.p };
 		case TIf(e, econd, eelse):
 			var e = mapExpr(e, true);
 			var econd = mapExpr(econd, isVar);

+ 20 - 0
hxsl/GlslOut.hx

@@ -27,6 +27,12 @@ class GlslOut {
 		m.set(Mat3x4, "_mat3x4");
 		m.set(VertexID, "gl_VertexID");
 		m.set(InstanceID, "gl_InstanceID");
+		m.set(IVec2, "ivec2");
+		m.set(IVec3, "ivec3");
+		m.set(IVec4, "ivec4");
+		m.set(BVec2, "bvec2");
+		m.set(BVec3, "bvec3");
+		m.set(BVec4, "bvec4");
 		for( g in m )
 			KWDS.set(g, true);
 		m;
@@ -246,6 +252,12 @@ class GlslOut {
 				return "textureCubeLodEXT";
 			default:
 			}
+		case Texel, TexelLod:
+			// if ( isES2 )
+			// 	decl("vec4 _texelFetch(sampler2d tex, ivec2 pos, int lod) ...")
+			// 	return "_texelFetch";
+			// else
+				return "texelFetch";
 		case Mod if( rt == TInt && isES ):
 			decl("int _imod( int x, int y ) { return int(mod(float(x),float(y))); }");
 			return "_imod";
@@ -366,6 +378,14 @@ class GlslOut {
 			add("clamp(");
 			addValue(e, tabs);
 			add(", 0., 1.)");
+		case TCall({ e : TGlobal(g = Texel) }, args):
+			add(getFunName(g,args,e.t));
+			add("(");
+			for( e in args ) {
+				addValue(e, tabs);
+				add(", ");
+			}
+			add("0)");
 		case TCall(v, args):
 			switch( v.e ) {
 			case TGlobal(g):

+ 28 - 0
hxsl/HlslOut.hx

@@ -27,6 +27,12 @@ class HlslOut {
 		m.set(Inversesqrt, "rsqrt");
 		m.set(VertexID,"_in.vertexID");
 		m.set(InstanceID,"_in.instanceID");
+		m.set(IVec2, "int2");
+		m.set(IVec3, "int3");
+		m.set(IVec4, "int3");
+		m.set(BVec2, "bool2");
+		m.set(BVec3, "bool3");
+		m.set(BVec4, "bool4");
 		for( g in m )
 			KWDS.set(g, true);
 		m;
@@ -254,6 +260,28 @@ class HlslOut {
 				addValue(args[i],tabs);
 			}
 			add(")");
+		case TCall({ e : TGlobal(g = (Texel | TexelLod)) }, args):
+			addValue(args[0], tabs);
+			add(".Load(");
+			switch ( args[1].t ) {
+				case TSampler2D:
+					add("int3(");
+				case TSampler2DArray:
+					add("int4(");
+				default:
+					throw "assert";
+			}
+			addValue(args[1],tabs);
+			switch( g ) {
+				case Texel:
+					add(", 0");
+				case TexelLod:
+					add(", ");
+					addValue(args[2],tabs);
+				default:
+					throw "assert";
+			}
+			add("))");
 		case TCall(e = { e : TGlobal(g) }, args):
 			switch( [g,args.length] ) {
 			case [Vec2, 1] if( args[0].t == TFloat ):