ShaderCache.hx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package h3d.impl;
  2. class ShaderCache {
  3. var file : String;
  4. var outputFile : String;
  5. var data : Map<String, haxe.io.Bytes>;
  6. var sources : Map<String, String>;
  7. var sourceFile : String;
  8. public var keepSource : Bool;
  9. public function new( file : String, ?outputFile : String ) {
  10. this.file = file;
  11. this.outputFile = outputFile ?? file;
  12. sourceFile = file + ".source";
  13. }
  14. public function disableSave() {
  15. outputFile = null;
  16. }
  17. public function initEmpty() {
  18. data = [];
  19. sources = [];
  20. }
  21. function load() {
  22. data = new Map();
  23. try loadFile(file) catch( e : Dynamic ) {};
  24. if( outputFile != file ) try loadFile(outputFile) catch( e : Dynamic ) {};
  25. if( keepSource ) try loadSources() catch( e : Dynamic ) {};
  26. }
  27. function loadFile( file : String ) {
  28. #if !sys
  29. throw "Cannot load shader cache with this platform";
  30. #else
  31. if( !sys.FileSystem.exists(file) )
  32. return;
  33. var cache = new haxe.io.BytesInput(sys.io.File.getBytes(file));
  34. while( cache.position < cache.length ) {
  35. var len = cache.readInt32();
  36. if( len < 0 || len > 4<<20 ) break;
  37. var key = cache.readString(len);
  38. if( key == "" ) break;
  39. var len = cache.readInt32();
  40. if( len < 0 || len > 4<<20 ) break;
  41. var str = cache.readString(len);
  42. data.set(key,haxe.crypto.Base64.decode(str));
  43. cache.readByte(); // newline
  44. }
  45. #end
  46. }
  47. function loadSources() {
  48. #if !sys
  49. throw "Cannot load shader cache with this platform";
  50. #else
  51. sources = new Map();
  52. if( !sys.FileSystem.exists(sourceFile) )
  53. return;
  54. var cache = new haxe.io.BytesInput(sys.io.File.getBytes(sourceFile));
  55. while( cache.position < cache.length ) {
  56. var len = cache.readInt32();
  57. if( len < 0 || len > 4<<20 ) break;
  58. var key = cache.readString(len);
  59. if( key == "" ) break;
  60. var len = cache.readInt32();
  61. if( len < 0 || len > 4<<20 ) break;
  62. var str = cache.readString(len);
  63. sources.set(key, str);
  64. cache.readByte(); // newline
  65. cache.readByte(); // newline
  66. }
  67. #end
  68. }
  69. public function resolveShaderBinary( source : String, ?configurationKey = "" ) {
  70. if( data == null ) load();
  71. return data.get(configurationKey + haxe.crypto.Md5.encode(source));
  72. }
  73. public function saveCompiledShader( source : String, bytes : haxe.io.Bytes, ?configurationKey = "", ?saveToFile = true ) {
  74. if( outputFile == null )
  75. return;
  76. if( data == null ) load();
  77. var key = configurationKey + haxe.crypto.Md5.encode(source);
  78. if( data.get(key) == bytes && (!keepSource || sources.get(key) == source) )
  79. return;
  80. data.set(key, bytes);
  81. if( saveToFile )
  82. save();
  83. if( keepSource ) {
  84. sources.set(key, source);
  85. saveSources();
  86. }
  87. }
  88. function save() {
  89. var out = new haxe.io.BytesOutput();
  90. var keys = Lambda.array({ iterator : data.keys });
  91. keys.sort(Reflect.compare);
  92. for( key in keys ) {
  93. out.writeInt32(key.length);
  94. out.writeString(key);
  95. var b64 = haxe.crypto.Base64.encode(data.get(key));
  96. out.writeInt32(b64.length);
  97. out.writeString(b64);
  98. out.writeByte('\n'.code);
  99. }
  100. #if sys
  101. try sys.io.File.saveBytes(outputFile, out.getBytes()) catch( e : Dynamic ) {};
  102. #end
  103. }
  104. function saveSources() {
  105. var out = new haxe.io.BytesOutput();
  106. var keys = Lambda.array({ iterator : sources.keys });
  107. keys.sort(Reflect.compare);
  108. for( key in keys ) {
  109. out.writeInt32(key.length);
  110. out.writeString(key);
  111. var src = sources.get(key);
  112. out.writeInt32(src.length);
  113. out.writeString(src);
  114. out.writeByte('\n'.code);
  115. out.writeByte('\n'.code);
  116. }
  117. #if sys
  118. try sys.io.File.saveBytes(sourceFile, out.getBytes()) catch( e : Dynamic ) {};
  119. #end
  120. }
  121. }