|
@@ -36,26 +36,32 @@ class ShaderConst {
|
|
|
}
|
|
|
|
|
|
class SharedShader {
|
|
|
-
|
|
|
public static var UNROLL_LOOPS = false;
|
|
|
+ static var SHADER_RESOLVE : Map<String, SharedShader> = [];
|
|
|
|
|
|
public var data : ShaderData;
|
|
|
public var globals : Array<ShaderGlobal>;
|
|
|
public var consts : ShaderConst;
|
|
|
var instanceCache : Map<Int,ShaderInstance>;
|
|
|
var paramsCount : Int;
|
|
|
+ var file : hxd.fs.FileEntry;
|
|
|
+ var module : String;
|
|
|
|
|
|
- public function new(src:String) {
|
|
|
+ public function new(src:String,?module:String) {
|
|
|
instanceCache = new Map();
|
|
|
consts = null;
|
|
|
globals = [];
|
|
|
if( src == "" )
|
|
|
return;
|
|
|
+ this.module = module;
|
|
|
data = new hxsl.Serializer().unserialize(src);
|
|
|
for( v in data.vars )
|
|
|
initVarId(v);
|
|
|
data = compactMem(data);
|
|
|
initialize();
|
|
|
+ #if !macro
|
|
|
+ initLiveReload();
|
|
|
+ #end
|
|
|
}
|
|
|
|
|
|
function initialize() {
|
|
@@ -177,7 +183,7 @@ class SharedShader {
|
|
|
}
|
|
|
default:
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
eval.inlineCalls = true;
|
|
|
eval.unrollLoops = UNROLL_LOOPS;
|
|
|
var edata = eval.eval(data);
|
|
@@ -257,6 +263,119 @@ class SharedShader {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ #if !macro
|
|
|
+
|
|
|
+ function initLiveReload() {
|
|
|
+ if( module == null )
|
|
|
+ return;
|
|
|
+ if( hxd.fs.SourceLoader.isActive() )
|
|
|
+ SHADER_RESOLVE.set(data.name, this);
|
|
|
+ var path = module.split(".").join("/")+".hx";
|
|
|
+ file = hxd.fs.SourceLoader.resolve(path);
|
|
|
+ if( file != null )
|
|
|
+ file.watch(onFileReload);
|
|
|
+ else
|
|
|
+ trace("Could not live reload shader "+data.name);
|
|
|
+ }
|
|
|
+
|
|
|
+ function onFileReload() {
|
|
|
+ // reload all shaders within the same file
|
|
|
+ for( sh in SHADER_RESOLVE )
|
|
|
+ if( sh.file == file )
|
|
|
+ sh.reloadShader();
|
|
|
+ }
|
|
|
+
|
|
|
+ function reloadShader() {
|
|
|
+ try {
|
|
|
+ var expr = loadShader(file, data.name);
|
|
|
+ if( expr == null )
|
|
|
+ return;
|
|
|
+ var checker = new hxsl.Checker();
|
|
|
+ checker.loadShader = function(name) {
|
|
|
+ var sh = SHADER_RESOLVE.get(name);
|
|
|
+ if( sh == null )
|
|
|
+ throw "Could not resolve shader "+name;
|
|
|
+ if( sh.file == null )
|
|
|
+ throw "Shader "+name+" can't be live reload because of missing live path";
|
|
|
+ return loadShader(sh.file, sh.data.name);
|
|
|
+ };
|
|
|
+ var data = checker.check(data.name,expr);
|
|
|
+ applyChanges(data);
|
|
|
+ } catch( e : hxsl.Ast.Error ) {
|
|
|
+ var line = file.getText().substr(0,e.pos.min).split("\n").length;
|
|
|
+ #if sys
|
|
|
+ Sys.println(e.pos.file+":"+line+": "+e.msg);
|
|
|
+ #else
|
|
|
+ haxe.Log.trace(e.msg,{ methodName: null, className: null, fileName : e.pos.file, lineNumber : line });
|
|
|
+ #end
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ static function mergeVars( vl : Array<TVar>, vl2 : Array<TVar> ) {
|
|
|
+ if( vl.length != vl2.length )
|
|
|
+ return false;
|
|
|
+ for( i => v in vl ) {
|
|
|
+ var v2 = vl2[i];
|
|
|
+ if( v.name != v2.name )
|
|
|
+ return false;
|
|
|
+ v2.id = v.id; // copy ids
|
|
|
+ switch( [v.type, v2.type] ) {
|
|
|
+ case [TStruct(vl),TStruct(vl2)]:
|
|
|
+ if( vl.length != vl2.length ) return false;
|
|
|
+ if( !mergeVars(vl, vl2) )
|
|
|
+ return false;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function applyChanges( data2 : ShaderData ) {
|
|
|
+ if( !mergeVars(data.vars, data2.vars) )
|
|
|
+ return false;
|
|
|
+ data = compactMem(data2);
|
|
|
+ instanceCache = new Map();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ static function loadShader( fs : hxd.fs.FileEntry, name : String ) : Ast.Expr {
|
|
|
+ var text = fs.getText();
|
|
|
+ #if !hscript
|
|
|
+ throw "Shader live reload requires --library hscript";
|
|
|
+ return null;
|
|
|
+ #else
|
|
|
+ var parser = new hscript.Parser();
|
|
|
+ var m = try parser.parseModule(text,fs.path) catch( e : hscript.Expr.Error ) {
|
|
|
+ Sys.println(e.toString());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ var clName = name.split(".").pop();
|
|
|
+ var found = null;
|
|
|
+ for( def in m )
|
|
|
+ switch( def ) {
|
|
|
+ case DClass(c) if( c.name == clName ):
|
|
|
+ for( f in c.fields )
|
|
|
+ if( f.name == "SRC" ) {
|
|
|
+ switch( f.kind ) {
|
|
|
+ case KVar(v): found = v.expr;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ // no matching class with SRC found in this module
|
|
|
+ if( found == null )
|
|
|
+ return null;
|
|
|
+ var expr = new hscript.Macro({ file : fs.path, min : 0, max : 0 }).convert(found);
|
|
|
+ var expr = new hxsl.MacroParser().parseExpr(expr);
|
|
|
+ return expr;
|
|
|
+ #end
|
|
|
+ }
|
|
|
+
|
|
|
+ #end
|
|
|
+
|
|
|
public static function compactMem<T>( mem : T ) {
|
|
|
#if (hl && heaps_compact_mem)
|
|
|
mem = hl.Api.compact(mem, null, 0, null);
|