Browse Source

hlsl output support for rwtextures

Nicolas Cannasse 1 year ago
parent
commit
8359fb6cdd
1 changed files with 164 additions and 127 deletions
  1. 164 127
      hxsl/HlslOut.hx

+ 164 - 127
hxsl/HlslOut.hx

@@ -14,8 +14,8 @@ class Samplers {
 	public function make( v : TVar, arr : Array<Int> ) : Array<Int> {
 	public function make( v : TVar, arr : Array<Int> ) : Array<Int> {
 
 
 		var ntex = switch( v.type ) {
 		var ntex = switch( v.type ) {
-		case TArray(t, SConst(k)) if( t.isSampler() ): k;
-		case t if( t.isSampler() ): 1;
+		case TArray(t, SConst(k)) if( t.isTexture() ): k;
+		case t if( t.isTexture() ): 1;
 		default:
 		default:
 			return null;
 			return null;
 		}
 		}
@@ -70,8 +70,6 @@ class HlslOut {
 		m.set(Fract, "frac");
 		m.set(Fract, "frac");
 		m.set(Mix, "lerp");
 		m.set(Mix, "lerp");
 		m.set(Inversesqrt, "rsqrt");
 		m.set(Inversesqrt, "rsqrt");
-		m.set(VertexID,"_in.vertexID");
-		m.set(InstanceID,"_in.instanceID");
 		m.set(IVec2, "int2");
 		m.set(IVec2, "int2");
 		m.set(IVec3, "int3");
 		m.set(IVec3, "int3");
 		m.set(IVec4, "int4");
 		m.set(IVec4, "int4");
@@ -79,7 +77,6 @@ class HlslOut {
 		m.set(BVec3, "bool3");
 		m.set(BVec3, "bool3");
 		m.set(BVec4, "bool4");
 		m.set(BVec4, "bool4");
 		m.set(FragCoord,"_in.__pos__");
 		m.set(FragCoord,"_in.__pos__");
-		m.set(FrontFacing, "_in.isFrontFace");
 		m.set(FloatBitsToInt, "asint");
 		m.set(FloatBitsToInt, "asint");
 		m.set(FloatBitsToUint, "asuint");
 		m.set(FloatBitsToUint, "asuint");
 		m.set(IntBitsToFloat, "asfloat");
 		m.set(IntBitsToFloat, "asfloat");
@@ -92,9 +89,6 @@ class HlslOut {
 
 
 	var SV_POSITION = "SV_POSITION";
 	var SV_POSITION = "SV_POSITION";
 	var SV_TARGET = "SV_TARGET";
 	var SV_TARGET = "SV_TARGET";
-	var SV_VertexID = "SV_VertexID";
-	var SV_InstanceID = "SV_InstanceID";
-	var SV_IsFrontFace = "SV_IsFrontFace";
 	var STATIC = "static ";
 	var STATIC = "static ";
 	var CONST = "const ";
 	var CONST = "const ";
 	var buf : StringBuf;
 	var buf : StringBuf;
@@ -121,6 +115,19 @@ class HlslOut {
 		allNames = new Map();
 		allNames = new Map();
 	}
 	}
 
 
+	function getSVName( g : TGlobal ) {
+		return switch( g ) {
+		case VertexID: "SV_VertexID";
+		case InstanceID: "SV_InstanceID";
+		case FrontFacing: "SV_IsFrontFace";
+		case ComputeVar_GlobalInvocation: "SV_DispatchThreadID";
+		case ComputeVar_LocalInvocation: "SV_GroupThreadID";
+		case ComputeVar_WorkGroup: "SV_GroupID";
+		case ComputeVar_LocalInvocationIndex: "SV_GroupIndex";
+		default: null;
+		}
+	}
+
 	inline function add( v : Dynamic ) {
 	inline function add( v : Dynamic ) {
 		buf.add(v);
 		buf.add(v);
 	}
 	}
@@ -167,12 +174,8 @@ class HlslOut {
 			add("float4x4");
 			add("float4x4");
 		case TMat3x4:
 		case TMat3x4:
 			add("float4x3");
 			add("float4x3");
-		case TSampler2D:
-			add("Texture2D");
-		case TSamplerCube:
-			add("TextureCube");
-		case TSampler2DArray:
-			add("Texture2DArray");
+		case TSampler(_), TRWTexture(_):
+			add(getTexType(t));
 		case TStruct(vl):
 		case TStruct(vl):
 			add("struct { ");
 			add("struct { ");
 			for( v in vl ) {
 			for( v in vl ) {
@@ -208,7 +211,7 @@ class HlslOut {
 
 
 	function addVar( v : TVar ) {
 	function addVar( v : TVar ) {
 		switch( v.type ) {
 		switch( v.type ) {
-		case TArray(t, size), TBuffer(t,size,_):
+		case TArray(t, size), TBuffer(t,size,Uniform):
 			addVar({
 			addVar({
 				id : v.id,
 				id : v.id,
 				name : v.name,
 				name : v.name,
@@ -216,6 +219,11 @@ class HlslOut {
 				kind : v.kind,
 				kind : v.kind,
 			});
 			});
 			addArraySize(size);
 			addArraySize(size);
+		case TBuffer(t, size, RW):
+			add('RWStructuredBuffer<');
+			addType(t);
+			add('> ');
+			ident(v);
 		default:
 		default:
 			addType(v.type);
 			addType(v.type);
 			add(" ");
 			add(" ");
@@ -287,6 +295,102 @@ class HlslOut {
 		decl("float4 mod(float4 x, float4 y) { return x - y * floor(x/y); }");
 		decl("float4 mod(float4 x, float4 y) { return x - y * floor(x/y); }");
 	}
 	}
 
 
+	function getTexType( t : Type ) {
+		return switch( t ) {
+		case TSampler(dim, arr): "Texture"+dim.getName().substr(1)+(arr?"Array":"");
+		case TRWTexture(dim, arr, chans): "RWTexture"+dim.getName().substr(1)+(arr?"Array":"")+"<"+(chans==1?"float":"float"+chans)+">";
+		default: throw "assert";
+		}
+	}
+
+	function declGlobal( g : TGlobal, args : Array<TExpr> ) {
+		switch( g ) {
+		case Mat3x4:
+			// float4x3 constructor uses row-order, we want column order here
+			decl("float4x3 mat3x4( float4 a, float4 b, float4 c ) { float4x3 m; m._m00_m10_m20_m30 = a; m._m01_m11_m21_m31 = b; m._m02_m12_m22_m32 = c; return m; }");
+			decl("float4x3 mat3x4( float4x4 m ) { float4x3 m2; m2._m00_m10_m20_m30 = m._m00_m10_m20_m30; m2._m01_m11_m21_m31 = m._m01_m11_m21_m31; m2._m02_m12_m22_m32 = m._m02_m12_m22_m32; return m2; }");
+		case Mat4:
+			decl("float4x4 mat4( float4 a, float4 b, float4 c, float4 d ) { float4x4 m; m._m00_m10_m20_m30 = a; m._m01_m11_m21_m31 = b; m._m02_m12_m22_m32 = c; m._m03_m13_m23_m33 = d; return m; }");
+		case Mat3:
+			decl("float3x3 mat3( float4x4 m ) { return (float3x3)m; }");
+			decl("float3x3 mat3( float4x3 m ) { return (float3x3)m; }");
+			decl("float3x3 mat3( float3 a, float3 b, float3 c ) { float3x3 m; m._m00_m10_m20 = a; m._m01_m11_m21 = b; m._m02_m12_m22 = c; return m; }");
+			decl("float3x3 mat3( float c00, float c01, float c02, float c10, float c11, float c12, float c20, float c21, float c22 ) { float3x3 m = { c00, c10, c20, c01, c11, c21, c02, c12, c22 }; return m; }");
+		case Mat2:
+			decl("float2x2 mat2( float4x4 m ) { return (float2x2)m; }");
+			decl("float2x2 mat2( float4x3 m ) { return (float2x2)m; }");
+			decl("float2x2 mat2( float3x3 m ) { return (float2x2)m; }");
+			decl("float2x2 mat2( float2 a, float2 b ) { float2x2 m; m._m00_m10 = a; m._m01_m11 = b; return m; }");
+			decl("float2x2 mat2( float c00, float c01, float c10, float c11 ) { float2x2 m = { c00, c10, c01, c11 }; return m; }");
+		case Mod:
+			declMods();
+		case Pow:
+			// negative power might not work
+			decl("#pragma warning(disable:3571)");
+		case Pack:
+			decl("float4 pack( float v ) { float4 color = frac(v * float4(1, 255, 255.*255., 255.*255.*255.)); return color - color.yzww * float4(1. / 255., 1. / 255., 1. / 255., 0.); }");
+		case Unpack:
+			decl("float unpack( float4 color ) { return dot(color,float4(1., 1. / 255., 1. / (255. * 255.), 1. / (255. * 255. * 255.))); }");
+		case PackNormal:
+			decl("float4 packNormal( float3 n ) { return float4((n + 1.) * 0.5,1.); }");
+		case UnpackNormal:
+			decl("float3 unpackNormal( float4 p ) { return normalize(p.xyz * 2. - 1.); }");
+		case Atan:
+			decl("float atan( float y, float x ) { return atan2(y,x); }");
+		case ScreenToUv:
+			decl("float2 screenToUv( float2 v ) { return v * float2(0.5, -0.5) + float2(0.5,0.5); }");
+		case UvToScreen:
+			decl("float2 uvToScreen( float2 v ) { return v * float2(2.,-2.) + float2(-1., 1.); }");
+		case DFdx:
+			decl("float dFdx( float v ) { return ddx(v); }");
+			decl("float2 dFdx( float2 v ) { return ddx(v); }");
+			decl("float3 dFdx( float3 v ) { return ddx(v); }");
+		case DFdy:
+			decl("float dFdy( float v ) { return ddy(v); }");
+			decl("float2 dFdy( float2 v ) { return ddy(v); }");
+			decl("float3 dFdy( float3 v ) { return ddy(v); }");
+		case UintBitsToFloat:
+			decl("float _uintBitsToFloat( int v ) { return asfloat(asuint(v)); }");
+			decl("float2 _uintBitsToFloat( int2 v ) { return asfloat(asuint(v)); }");
+			decl("float3 _uintBitsToFloat( int3 v ) { return asfloat(asuint(v)); }");
+			decl("float4 _uintBitsToFloat( int4 v ) { return asfloat(asuint(v)); }");
+		case TextureSize:
+			var tt = args[0].t;
+			var tstr = getTexType(tt);
+			switch( tt ) {
+			case TSampler(dim, arr) if( args.length > 1 ):
+				var size = Tools.getDimSize(dim, arr);
+				switch( size ) {
+				case 1:
+					decl('float textureSize($tstr tex, int lod) { float w; float levels; tex.GetDimensions((uint)lod,w,levels); return w; }');
+				case 2:
+					decl('float2 textureSize($tstr tex, int lod) { float w; float h; float levels; tex.GetDimensions((uint)lod,w,h,levels); return float2(w, h); }');
+				case 3:
+					decl('float3 textureSize($tstr tex, int lod) { float w; float h; float els; float levels; tex.GetDimensions((uint)lod,w,h,els,levels); return float3(w, h, els); }');
+				}
+			case TSampler(dim,arr), TRWTexture(dim, arr, _):
+				var size = Tools.getDimSize(dim, arr);
+				switch( size ) {
+				case 1:
+					decl('float textureSize($tstr tex) { float w; tex.GetDimensions(w); return w; }');
+				case 2:
+					decl('float2 textureSize($tstr tex) { float w; float h; tex.GetDimensions(w,h); return float2(w, h); }');
+				case 3:
+					decl('float3 textureSize($tstr tex) { float w; float h; float els; tex.GetDimensions(w,h,els); return float3(w, h, els); }');
+				}
+			default:
+				throw "assert";
+			}
+		case Vec2 if( args.length == 1 && args[0].t == TFloat ):
+			decl("float2 vec2( float v ) { return float2(v,v); }");
+		case Vec3 if( args.length == 1 && args[0].t == TFloat ):
+			decl("float3 vec3( float v ) { return float3(v,v,v); }");
+		case Vec4 if( args.length == 1 && args[0].t == TFloat ):
+			decl("float4 vec4( float v ) { return float4(v,v,v,v); }");
+		default:
+		}
+	}
+
 	function addExpr( e : TExpr, tabs : String ) {
 	function addExpr( e : TExpr, tabs : String ) {
 		switch( e.e ) {
 		switch( e.e ) {
 		case TConst(c):
 		case TConst(c):
@@ -337,16 +441,21 @@ class HlslOut {
 			if( g == Texture && isVertex )
 			if( g == Texture && isVertex )
 				add(",0");
 				add(",0");
 			add(")");
 			add(")");
+		case TCall({ e : TGlobal(ImageStore) }, [tex,uv,color]):
+			addValue(tex, tabs);
+			add("[");
+			addValue(uv, tabs);
+			add("] = ");
+			addValue(color, tabs);
 		case TCall({ e : TGlobal(g = (Texel)) }, args):
 		case TCall({ e : TGlobal(g = (Texel)) }, args):
 			addValue(args[0], tabs);
 			addValue(args[0], tabs);
 			add(".Load(");
 			add(".Load(");
-			switch ( args[1].t ) {
-				case TSampler2D:
-					add("int3(");
-				case TSampler2DArray:
-					add("int4(");
-				default:
-					throw "assert";
+			switch( args[1].t ) {
+			case TSampler(dim,arr):
+				var size = Tools.getDimSize(dim, arr) + 1;
+				add("int"+size+"(");
+			default:
+				throw "assert";
 			}
 			}
 			addValue(args[1],tabs);
 			addValue(args[1],tabs);
 			if ( args.length != 2 ) {
 			if ( args.length != 2 ) {
@@ -357,34 +466,9 @@ class HlslOut {
 				add(", 0");
 				add(", 0");
 			}
 			}
 			add("))");
 			add("))");
-		case TCall({ e : TGlobal(g = (TextureSize)) }, args):
-			decl("float2 textureSize(Texture2D tex, int lod) { float w; float h; float levels; tex.GetDimensions((uint)lod,w,h,levels); return float2(w, h); }");
-			decl("float3 textureSize(Texture2DArray tex, int lod) { float w; float h; float els; float levels; tex.GetDimensions((uint)lod,w,h,els,levels); return float3(w, h, els); }");
-			decl("float2 textureSize(TextureCube tex, int lod) { float w; float h; float levels; tex.GetDimensions((uint)lod,w,h,levels); return float2(w, h); }");
-			add("textureSize(");
-			addValue(args[0], tabs);
-			if (args.length != 1) {
-				// With LOD argument
-				add(", ");
-				addValue(args[1],tabs);
-			} else {
-				add(", 0");
-			}
-			add(")");
 		case TCall(e = { e : TGlobal(g) }, args):
 		case TCall(e = { e : TGlobal(g) }, args):
-			switch( [g,args.length] ) {
-			case [Vec2, 1] if( args[0].t == TFloat ):
-				decl("float2 vec2( float v ) { return float2(v,v); }");
-				add("vec2");
-			case [Vec3, 1] if( args[0].t == TFloat ):
-				decl("float3 vec3( float v ) { return float3(v,v,v); }");
-				add("vec3");
-			case [Vec4, 1] if( args[0].t == TFloat ):
-				decl("float4 vec4( float v ) { return float4(v,v,v,v); }");
-				add("vec4");
-			default:
-				addValue(e,tabs);
-			}
+			declGlobal(g, args);
+			addValue(e,tabs);
 			add("(");
 			add("(");
 			var first = true;
 			var first = true;
 			for( e in args ) {
 			for( e in args ) {
@@ -393,58 +477,6 @@ class HlslOut {
 			}
 			}
 			add(")");
 			add(")");
 		case TGlobal(g):
 		case TGlobal(g):
-			switch( g ) {
-			case Mat3x4:
-				// float4x3 constructor uses row-order, we want column order here
-				decl("float4x3 mat3x4( float4 a, float4 b, float4 c ) { float4x3 m; m._m00_m10_m20_m30 = a; m._m01_m11_m21_m31 = b; m._m02_m12_m22_m32 = c; return m; }");
-				decl("float4x3 mat3x4( float4x4 m ) { float4x3 m2; m2._m00_m10_m20_m30 = m._m00_m10_m20_m30; m2._m01_m11_m21_m31 = m._m01_m11_m21_m31; m2._m02_m12_m22_m32 = m._m02_m12_m22_m32; return m2; }");
-			case Mat4:
-				decl("float4x4 mat4( float4 a, float4 b, float4 c, float4 d ) { float4x4 m; m._m00_m10_m20_m30 = a; m._m01_m11_m21_m31 = b; m._m02_m12_m22_m32 = c; m._m03_m13_m23_m33 = d; return m; }");
-			case Mat3:
-				decl("float3x3 mat3( float4x4 m ) { return (float3x3)m; }");
-				decl("float3x3 mat3( float4x3 m ) { return (float3x3)m; }");
-				decl("float3x3 mat3( float3 a, float3 b, float3 c ) { float3x3 m; m._m00_m10_m20 = a; m._m01_m11_m21 = b; m._m02_m12_m22 = c; return m; }");
-				decl("float3x3 mat3( float c00, float c01, float c02, float c10, float c11, float c12, float c20, float c21, float c22 ) { float3x3 m = { c00, c10, c20, c01, c11, c21, c02, c12, c22 }; return m; }");
-			case Mat2:
-				decl("float2x2 mat2( float4x4 m ) { return (float2x2)m; }");
-				decl("float2x2 mat2( float4x3 m ) { return (float2x2)m; }");
-				decl("float2x2 mat2( float3x3 m ) { return (float2x2)m; }");
-				decl("float2x2 mat2( float2 a, float2 b ) { float2x2 m; m._m00_m10 = a; m._m01_m11 = b; return m; }");
-				decl("float2x2 mat2( float c00, float c01, float c10, float c11 ) { float2x2 m = { c00, c10, c01, c11 }; return m; }");
-			case Mod:
-				declMods();
-			case Pow:
-				// negative power might not work
-				decl("#pragma warning(disable:3571)");
-			case Pack:
-				decl("float4 pack( float v ) { float4 color = frac(v * float4(1, 255, 255.*255., 255.*255.*255.)); return color - color.yzww * float4(1. / 255., 1. / 255., 1. / 255., 0.); }");
-			case Unpack:
-				decl("float unpack( float4 color ) { return dot(color,float4(1., 1. / 255., 1. / (255. * 255.), 1. / (255. * 255. * 255.))); }");
-			case PackNormal:
-				decl("float4 packNormal( float3 n ) { return float4((n + 1.) * 0.5,1.); }");
-			case UnpackNormal:
-				decl("float3 unpackNormal( float4 p ) { return normalize(p.xyz * 2. - 1.); }");
-			case Atan:
-				decl("float atan( float y, float x ) { return atan2(y,x); }");
-			case ScreenToUv:
-				decl("float2 screenToUv( float2 v ) { return v * float2(0.5, -0.5) + float2(0.5,0.5); }");
-			case UvToScreen:
-				decl("float2 uvToScreen( float2 v ) { return v * float2(2.,-2.) + float2(-1., 1.); }");
-			case DFdx:
-				decl("float dFdx( float v ) { return ddx(v); }");
-				decl("float2 dFdx( float2 v ) { return ddx(v); }");
-				decl("float3 dFdx( float3 v ) { return ddx(v); }");
-			case DFdy:
-				decl("float dFdy( float v ) { return ddy(v); }");
-				decl("float2 dFdy( float2 v ) { return ddy(v); }");
-				decl("float3 dFdy( float3 v ) { return ddy(v); }");
-			case UintBitsToFloat:
-				decl("float _uintBitsToFloat( int v ) { return asfloat(asuint(v)); }");
-				decl("float2 _uintBitsToFloat( int2 v ) { return asfloat(asuint(v)); }");
-				decl("float3 _uintBitsToFloat( int3 v ) { return asfloat(asuint(v)); }");
-				decl("float4 _uintBitsToFloat( int4 v ) { return asfloat(asuint(v)); }");
-			default:
-			}
 			add(GLOBALS.get(g));
 			add(GLOBALS.get(g));
 		case TParenthesis(e):
 		case TParenthesis(e):
 			add("(");
 			add("(");
@@ -700,11 +732,15 @@ class HlslOut {
 		}
 		}
 	}
 	}
 
 
-	function collectGlobals( m : Map<TGlobal,Bool>, e : TExpr ) {
+	function collectGlobals( m : Map<TGlobal,Type>, e : TExpr ) {
 		switch( e.e )  {
 		switch( e.e )  {
-		case TGlobal(g): m.set(g,true);
+		case TGlobal(g): m.set(g,e.t);
 		case TCall({ e : TGlobal(SetLayout) }, [{ e : TConst(CInt(x)) }, { e : TConst(CInt(y)) }, { e : TConst(CInt(z)) }]):
 		case TCall({ e : TGlobal(SetLayout) }, [{ e : TConst(CInt(x)) }, { e : TConst(CInt(y)) }, { e : TConst(CInt(z)) }]):
 			computeLayout = [x,y,z];
 			computeLayout = [x,y,z];
+		case TCall({ e : TGlobal(SetLayout) }, [{ e : TConst(CInt(x)) }, { e : TConst(CInt(y)) }]):
+			computeLayout = [x,y,1];
+		case TCall({ e : TGlobal(SetLayout) }, [{ e : TConst(CInt(x)) }]):
+			computeLayout = [x,1,1];
 		default: e.iter(collectGlobals.bind(m));
 		default: e.iter(collectGlobals.bind(m));
 		}
 		}
 	}
 	}
@@ -732,12 +768,19 @@ class HlslOut {
 		for( v in s.vars )
 		for( v in s.vars )
 			if( v.kind == Input || (v.kind == Var && !isVertex) )
 			if( v.kind == Input || (v.kind == Var && !isVertex) )
 				declVar("_in.", v);
 				declVar("_in.", v);
-		if( foundGlobals.exists(VertexID) )
-			add("\tuint vertexID : "+SV_VertexID+";\n");
-		if( foundGlobals.exists(InstanceID) )
-			add("\tuint instanceID : "+SV_InstanceID+";\n");
-		if( foundGlobals.exists(FrontFacing) )
-			add("\tbool isFrontFace : "+SV_IsFrontFace+";\n");
+		for( g in foundGlobals.keys() ) {
+			var sv = getSVName(g);
+			if( sv == null ) continue;
+			add("\t");
+			addType(foundGlobals.get(g));
+			var name = g.getName().split("_").pop();
+			name = name.charAt(0).toLowerCase()+name.substr(1);
+			add(" "+name);
+			add(" : ");
+			add(sv);
+			add(";\n");
+			GLOBALS.set(g, "_in."+name);
+		}
 		add("};\n\n");
 		add("};\n\n");
 
 
 		if( !isCompute ) {
 		if( !isCompute ) {
@@ -770,14 +813,17 @@ class HlslOut {
 		for( v in s.vars )
 		for( v in s.vars )
 			if( v.kind == Param ) {
 			if( v.kind == Param ) {
 				switch( v.type ) {
 				switch( v.type ) {
-				case TArray(t, _) if( t.isSampler() ):
+				case TArray(TRWTexture(_), _):
+					buffers.push(v);
+					continue;
+				case TArray(t, _) if( t.isTexture() ):
 					textures.push(v);
 					textures.push(v);
 					continue;
 					continue;
 				case TBuffer(_):
 				case TBuffer(_):
 					buffers.push(v);
 					buffers.push(v);
 					continue;
 					continue;
 				default:
 				default:
-					if( v.type.isSampler() ) {
+					if( v.type.isTexture() ) {
 						textures.push(v);
 						textures.push(v);
 						continue;
 						continue;
 					}
 					}
@@ -791,24 +837,15 @@ class HlslOut {
 		var bufCount = 0;
 		var bufCount = 0;
 		for( b in buffers ) {
 		for( b in buffers ) {
 			switch( b.type ) {
 			switch( b.type ) {
-			case TBuffer(t, size, kind):
-				switch( kind ) {
-				case Uniform:
-					add('cbuffer _buffer$bufCount : register(b${bufCount+baseRegister+2}) { ');
-					addVar(b);
-					add("; };\n");
-					bufCount++;
-				case RW:
-					add('RWStructuredBuffer<');
-					addType(t);
-					add('> ');
-					ident(b);
-					add(' : register(u${bufCount+baseRegister+2});');
-					bufCount++;
-				}
+			case TBuffer(t, size, Uniform):
+				add('cbuffer _buffer$bufCount : register(b${bufCount+baseRegister+2}) { ');
+				addVar(b);
+				add("; };\n");
 			default:
 			default:
-				throw "assert";
+				addVar(b);
+				add(' : register(u${bufCount+baseRegister+2});\n');
 			}
 			}
+			bufCount++;
 		}
 		}
 		if( bufCount > 0 ) add("\n");
 		if( bufCount > 0 ) add("\n");