diff --git a/hxsl/Ast.hx b/hxsl/Ast.hx index 6b73fbcc62..d77f49dca2 100644 --- a/hxsl/Ast.hx +++ b/hxsl/Ast.hx @@ -291,6 +291,7 @@ enum TGlobal { InstanceID; // gl globals FragCoord; + FragDepth; FrontFacing; // bit casting FloatBitsToInt; @@ -522,6 +523,8 @@ class Tools { return hasSideEffect(it) || hasSideEffect(loop); case TArray(e, index): return hasSideEffect(e) || hasSideEffect(index); + case TGlobal(FragDepth): + return true; case TConst(_), TVar(_), TGlobal(_): return false; case TCall({ e : TGlobal(SetLayout) },_): diff --git a/hxsl/Checker.hx b/hxsl/Checker.hx index d55d5f9a22..9bd9c2b8db 100644 --- a/hxsl/Checker.hx +++ b/hxsl/Checker.hx @@ -186,7 +186,7 @@ class Checker { ]; case ImageStore: []; - case VertexID, InstanceID, FragCoord, FrontFacing: + case VertexID, InstanceID, FragCoord, FrontFacing,FragDepth: null; case AtomicAdd: [{ args : [{ name : "buf", type : TBuffer(TInt, SConst(0), RW) },{ name : "index", type : TInt }, { name : "data", type : TInt }], ret : TInt }]; @@ -225,6 +225,7 @@ class Checker { globals.set("vertexID", { t : TInt, g : VertexID }); globals.set("instanceID", { t : TInt, g : InstanceID }); globals.set("fragCoord", { t : vec4, g : FragCoord }); + globals.set("fragDepth", { t : TFloat, g : FragDepth }); globals.set("frontFacing", { t : TBool, g : FrontFacing }); for( gname => vl in gvars ) globals.set(gname, { t : TStruct([ @@ -418,6 +419,8 @@ class Checker { case TArray(e, _): checkWrite(e); return; + case TGlobal(FragDepth): + return; default: } error("This expression cannot be assigned", e.p); diff --git a/hxsl/Dce.hx b/hxsl/Dce.hx index 3e85dbd989..382e81d6c0 100644 --- a/hxsl/Dce.hx +++ b/hxsl/Dce.hx @@ -62,6 +62,7 @@ class Dce { var used : Map; var channelVars : Array; var markAsKeep : Bool; + var fragDepthId = Tools.allocVarId(); public function new() { } @@ -202,6 +203,27 @@ class Dce { link(v, writeTo); case TSwiz({ e : TVar(v) }, swiz): link(v, writeTo, swizBits(swiz)); + case TBinop(op, { e : TGlobal(FragDepth) }, e2 ): + var v:TVar = { + id: fragDepthId, + name: "FragDepth", + type: TFloat, + kind: Global, + }; + var v = get(v); + switch(op) { + // Last assign will always clear all other dependencies + case OpAssign: + v.adeps = []; + v.deps.clear(); + case OpAssignOp(_): + default: + return; + } + v.keep = 15; + writeTo.push(v, 15); + check(e2, writeTo, isAffected); + writeTo.pop(); case TBinop(OpAssign | OpAssignOp(_), { e : TVar(v) }, e): var v = get(v); writeTo.push(v,15); @@ -296,6 +318,8 @@ class Dce { count++; } return { e : TBlock(out), p : e.p, t : e.t }; + case TBinop(OpAssign | OpAssignOp(_), {e: TGlobal(FragDepth) },{e: TVar(v) }) if(get(v).used == 0): + return { e : TConst(CNull), t : e.t, p : e.p }; case TVarDecl(v,_) | TBinop(OpAssign | OpAssignOp(_), { e : (TVar(v) | TSwiz( { e : TVar(v) }, _) | TArray( { e : TVar(v) }, _)) }, _) if( get(v).used == 0 ): return { e : TConst(CNull), t : e.t, p : e.p }; case TBinop(OpAssign | OpAssignOp(_), { e : TSwiz( { e : TVar(v) }, swiz) }, _) if( get(v).used & swizBits(swiz) == 0 ): diff --git a/hxsl/GlslOut.hx b/hxsl/GlslOut.hx index daf30e09f5..a2cf628d93 100644 --- a/hxsl/GlslOut.hx +++ b/hxsl/GlslOut.hx @@ -67,6 +67,7 @@ class GlslOut { set(BVec3, "bvec3"); set(BVec4, "bvec4"); set(FragCoord, "gl_FragCoord"); + set(FragDepth, "gl_FragDepth"); set(FrontFacing, "gl_FrontFacing"); set(FloatBitsToUint, "_floatBitsToUint"); set(UintBitsToFloat, "_uintBitsToFloat"); diff --git a/hxsl/Linker.hx b/hxsl/Linker.hx index b16c608f66..92e700a2aa 100644 --- a/hxsl/Linker.hx +++ b/hxsl/Linker.hx @@ -31,6 +31,7 @@ private class ShaderInfos { public var vertex : Null; public var onStack : Bool; public var hasDiscard : Bool; + public var hasFragDepth : Bool; public var isCompute : Bool; public var marked : Null; public function new(n, v) { @@ -201,6 +202,23 @@ class Linker { return { e : TVar(v.v), t : v.v.type, p : e.p }; case TBinop(op, e1, e2): switch( [op, e1.e] ) { + case [OpAssign | OpAssignOp(_), TGlobal(FragDepth)]: + if( curShader != null ) { + curShader.hasFragDepth = true; + } + + var e2 = mapExprVar(e2); + switch(e2.e) { + case TVar(v2): + var v2 = allocVar(v2,e2.p); + if( !curShader.readMap.exists(v2.id) ) { + curShader.readMap.set(v2.id, v2); + curShader.readVars.push(v2); + } + default: + } + + return { e : TBinop(op, { e : TGlobal(FragDepth),t : TFloat, p : e.p }, e2), t : e.t, p : e.p }; case [OpAssign, TVar(v)] if( !locals.exists(v.id) ): var e2 = mapExprVar(e2); var v = allocVar(v, e1.p); @@ -414,7 +432,7 @@ class Linker { // force shaders containing discard to be included for( s in shaders ) - if( s.hasDiscard || s.isCompute ) { + if( s.hasDiscard || s.isCompute || s.hasFragDepth) { initDependencies(s); entry.deps.set(s, true); }