NodeShader.hx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. package arm.shader;
  2. import zui.Nodes;
  3. import iron.data.SceneFormat;
  4. class NodeShader {
  5. public var context: NodeShaderContext;
  6. var shader_type = '';
  7. var includes: Array<String> = [];
  8. public var ins: Array<String> = [];
  9. public var outs: Array<String> = [];
  10. public var sharedSamplers: Array<String> = [];
  11. var uniforms: Array<String> = [];
  12. var functions = new Map<String, String>();
  13. public var main = '';
  14. public var main_init = '';
  15. public var main_end = '';
  16. public var main_normal = '';
  17. public var main_textures = '';
  18. public var main_attribs = '';
  19. var header = '';
  20. public var write_pre = false;
  21. public var write_normal = 0;
  22. public var write_textures = 0;
  23. var vstruct_as_vsin = true;
  24. var lock = false;
  25. // References
  26. public var bposition = false;
  27. public var wposition = false;
  28. public var mposition = false;
  29. public var vposition = false;
  30. public var wvpposition = false;
  31. public var ndcpos = false;
  32. public var wtangent = false;
  33. public var vVec = false;
  34. public var vVecCam = false;
  35. public var n = false;
  36. public var nAttr = false;
  37. public var dotNV = false;
  38. public var invTBN = false;
  39. public function new(context: NodeShaderContext, shader_type: String) {
  40. this.context = context;
  41. this.shader_type = shader_type;
  42. }
  43. public function add_include(s: String) {
  44. includes.push(s);
  45. }
  46. public function add_in(s: String) {
  47. ins.push(s);
  48. }
  49. public function add_out(s: String) {
  50. outs.push(s);
  51. }
  52. public function add_uniform(s: String, link: String = null, included = false) {
  53. var ar = s.split(' ');
  54. // layout(RGBA8) image3D voxels
  55. var utype = ar[ar.length - 2];
  56. var uname = ar[ar.length - 1];
  57. if (StringTools.startsWith(utype, 'sampler') || StringTools.startsWith(utype, 'image') || StringTools.startsWith(utype, 'uimage')) {
  58. var is_image = (StringTools.startsWith(utype, 'image') || StringTools.startsWith(utype, 'uimage')) ? true : false;
  59. context.add_texture_unit(utype, uname, link, is_image);
  60. }
  61. else {
  62. // Prefer vec4[] for d3d to avoid padding
  63. if (ar[0] == 'float' && ar[1].indexOf('[') >= 0) {
  64. ar[0] = 'floats';
  65. ar[1] = ar[1].split('[')[0];
  66. }
  67. else if (ar[0] == 'vec4' && ar[1].indexOf('[') >= 0) {
  68. ar[0] = 'floats';
  69. ar[1] = ar[1].split('[')[0];
  70. }
  71. context.add_constant(ar[0], ar[1], link);
  72. }
  73. if (included == false && uniforms.indexOf(s) == -1) {
  74. uniforms.push(s);
  75. }
  76. }
  77. public function add_shared_sampler(s: String) {
  78. if (sharedSamplers.indexOf(s) == -1) {
  79. sharedSamplers.push(s);
  80. var ar = s.split(' ');
  81. // layout(RGBA8) sampler2D tex
  82. var utype = ar[ar.length - 2];
  83. var uname = ar[ar.length - 1];
  84. context.add_texture_unit(utype, uname, null, false);
  85. }
  86. }
  87. public function add_function(s: String) {
  88. var fname = s.split('(')[0];
  89. if (functions.exists(fname)) return;
  90. functions.set(fname, s);
  91. }
  92. public function contains(s: String): Bool {
  93. return main.indexOf(s) >= 0 ||
  94. main_init.indexOf(s) >= 0 ||
  95. main_normal.indexOf(s) >= 0 ||
  96. ins.indexOf(s) >= 0 ||
  97. main_textures.indexOf(s) >= 0 ||
  98. main_attribs.indexOf(s) >= 0;
  99. }
  100. public function write_init(s: String) {
  101. main_init = s + '\n' + main_init;
  102. }
  103. public function write(s: String) {
  104. if (lock) return;
  105. if (write_textures > 0) {
  106. main_textures += s + '\n';
  107. }
  108. else if (write_normal > 0) {
  109. main_normal += s + '\n';
  110. }
  111. else if (write_pre) {
  112. main_init += s + '\n';
  113. }
  114. else {
  115. main += s + '\n';
  116. }
  117. }
  118. public function write_header(s: String) {
  119. header += s + '\n';
  120. }
  121. public function write_end(s: String) {
  122. main_end += s + '\n';
  123. }
  124. public function write_attrib(s: String) {
  125. main_attribs += s + '\n';
  126. }
  127. function dataSize(data: String): String {
  128. if (data == 'float1') return '1';
  129. else if (data == 'float2') return '2';
  130. else if (data == 'float3') return '3';
  131. else if (data == 'float4') return '4';
  132. else if (data == 'short2norm') return '2';
  133. else if (data == 'short4norm') return '4';
  134. else return '1';
  135. }
  136. function vstruct_to_vsin() {
  137. // if self.shader_type != 'vert' or self.ins != [] or not self.vstruct_as_vsin: # Vertex structure as vertex shader input
  138. // return
  139. var vs = context.data.vertex_elements;
  140. for (e in vs) {
  141. add_in('vec' + dataSize(e.data) + ' ' + e.name);
  142. }
  143. }
  144. public function get(): String {
  145. if (shader_type == 'vert' && vstruct_as_vsin) {
  146. vstruct_to_vsin();
  147. }
  148. var sharedSampler = 'shared_sampler';
  149. if (sharedSamplers.length > 0) {
  150. sharedSampler = sharedSamplers[0].split(' ')[1] + '_sampler';
  151. }
  152. #if (kha_direct3d11 || kha_direct3d12)
  153. var s = '#define HLSL\n';
  154. s += '#define textureArg(tex) Texture2D tex,SamplerState tex ## _sampler\n';
  155. s += '#define texturePass(tex) tex,tex ## _sampler\n';
  156. s += '#define sampler2D Texture2D\n';
  157. s += '#define sampler3D Texture3D\n';
  158. s += '#define texture(tex, coord) tex.Sample(tex ## _sampler, coord)\n';
  159. s += '#define textureShared(tex, coord) tex.Sample($sharedSampler, coord)\n';
  160. s += '#define textureLod(tex, coord, lod) tex.SampleLevel(tex ## _sampler, coord, lod)\n';
  161. s += '#define textureLodShared(tex, coord, lod) tex.SampleLevel($sharedSampler, coord, lod)\n';
  162. s += '#define texelFetch(tex, coord, lod) tex.Load(float3(coord.xy, lod))\n';
  163. s += 'uint2 _GetDimensions(Texture2D tex, uint lod) { uint x, y; tex.GetDimensions(x, y); return uint2(x, y); }\n';
  164. s += '#define textureSize _GetDimensions\n';
  165. s += '#define mod(a, b) (a % b)\n';
  166. s += '#define vec2 float2\n';
  167. s += '#define vec3 float3\n';
  168. s += '#define vec4 float4\n';
  169. s += '#define ivec2 int2\n';
  170. s += '#define ivec3 int3\n';
  171. s += '#define ivec4 int4\n';
  172. s += '#define mat2 float2x2\n';
  173. s += '#define mat3 float3x3\n';
  174. s += '#define mat4 float4x4\n';
  175. s += '#define dFdx ddx\n';
  176. s += '#define dFdy ddy\n';
  177. s += '#define inversesqrt rsqrt\n';
  178. s += '#define fract frac\n';
  179. s += '#define mix lerp\n';
  180. // s += '#define fma mad\n';
  181. s += header;
  182. var in_ext = '';
  183. var out_ext = '';
  184. for (a in includes) {
  185. s += '#include "' + a + '"\n';
  186. }
  187. // Input structure
  188. var index = 0;
  189. if (ins.length > 0) {
  190. s += 'struct SPIRV_Cross_Input {\n';
  191. index = 0;
  192. ins.sort(function(a, b): Int {
  193. // Sort inputs by name
  194. return a.substring(4) >= b.substring(4) ? 1 : -1;
  195. });
  196. for (a in ins) {
  197. s += '$a$in_ext : TEXCOORD$index;\n';
  198. index++;
  199. }
  200. // Built-ins
  201. if (shader_type == 'vert' && main.indexOf("gl_VertexID") >= 0) {
  202. s += 'uint gl_VertexID : SV_VertexID;\n';
  203. ins.push('uint gl_VertexID');
  204. }
  205. if (shader_type == 'vert' && main.indexOf("gl_InstanceID") >= 0) {
  206. s += 'uint gl_InstanceID : SV_InstanceID;\n';
  207. ins.push('uint gl_InstanceID');
  208. }
  209. s += '};\n';
  210. }
  211. // Output structure
  212. var num = 0;
  213. if (outs.length > 0 || shader_type == 'vert') {
  214. s += 'struct SPIRV_Cross_Output {\n';
  215. outs.sort(function(a, b): Int {
  216. // Sort outputs by name
  217. return a.substring(4) >= b.substring(4) ? 1 : -1;
  218. });
  219. index = 0;
  220. if (shader_type == 'vert') {
  221. for (a in outs) {
  222. s += '$a$out_ext : TEXCOORD$index;\n';
  223. index++;
  224. }
  225. s += 'float4 svpos : SV_POSITION;\n';
  226. }
  227. else {
  228. var out = outs[0];
  229. // Multiple render targets
  230. if (out.charAt(out.length - 1) == ']') {
  231. num = Std.parseInt(out.charAt(out.length - 2));
  232. s += 'vec4 fragColor[$num] : SV_TARGET0;\n';
  233. }
  234. else {
  235. s += 'vec4 fragColor : SV_TARGET0;\n';
  236. }
  237. }
  238. s += '};\n';
  239. }
  240. for (a in uniforms) {
  241. s += 'uniform ' + a + ';\n';
  242. if (StringTools.startsWith(a, 'sampler')) {
  243. s += 'SamplerState ' + a.split(' ')[1] + '_sampler;\n';
  244. }
  245. }
  246. if (sharedSamplers.length > 0) {
  247. for (a in sharedSamplers) {
  248. s += 'uniform ' + a + ';\n';
  249. }
  250. s += 'SamplerState $sharedSampler;\n';
  251. }
  252. for (f in functions) {
  253. s += f + '\n';
  254. }
  255. // Begin main
  256. if (outs.length > 0 || shader_type == 'vert') {
  257. if (ins.length > 0) {
  258. s += 'SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {\n';
  259. }
  260. else {
  261. s += 'SPIRV_Cross_Output main() {\n';
  262. }
  263. }
  264. else {
  265. if (ins.length > 0) {
  266. s += 'void main(SPIRV_Cross_Input stage_input) {\n';
  267. }
  268. else {
  269. s += 'void main() {\n';
  270. }
  271. }
  272. // Declare inputs
  273. for (a in ins) {
  274. var b = a.substring(5); // Remove type 'vec4 '
  275. s += '$a = stage_input.$b;\n';
  276. }
  277. if (shader_type == 'vert') {
  278. s += 'vec4 gl_Position;\n';
  279. for (a in outs) {
  280. s += '$a;\n';
  281. }
  282. }
  283. else {
  284. if (outs.length > 0) {
  285. if (num > 0) s += 'vec4 fragColor[$num];\n';
  286. else s += 'vec4 fragColor;\n';
  287. }
  288. }
  289. s += main_attribs;
  290. s += main_textures;
  291. s += main_normal;
  292. s += main_init;
  293. s += main;
  294. s += main_end;
  295. // Write output structure
  296. if (outs.length > 0 || shader_type == 'vert') {
  297. s += 'SPIRV_Cross_Output stage_output;\n';
  298. if (shader_type == 'vert') {
  299. s += 'gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n';
  300. s += 'stage_output.svpos = gl_Position;\n';
  301. for (a in outs) {
  302. var b = a.substring(5); // Remove type 'vec4 '
  303. s += 'stage_output.$b = $b;\n';
  304. }
  305. }
  306. else {
  307. if (num > 0) {
  308. for (i in 0...num) {
  309. s += 'stage_output.fragColor[$i] = fragColor[$i];\n';
  310. }
  311. }
  312. else {
  313. s += 'stage_output.fragColor = fragColor;\n';
  314. }
  315. }
  316. s += 'return stage_output;\n';
  317. }
  318. s += '}\n';
  319. #elseif kha_metal
  320. var s = '#define METAL\n';
  321. s += '#include <metal_stdlib>\n';
  322. s += '#include <simd/simd.h>\n';
  323. s += 'using namespace metal;\n';
  324. s += '#define textureArg(tex) texture2d<float> tex,sampler tex ## _sampler\n';
  325. s += '#define texturePass(tex) tex,tex ## _sampler\n';
  326. s += '#define sampler2D texture2d<float>\n';
  327. s += '#define sampler3D texture3d<float>\n';
  328. s += '#define texture(tex, coord) tex.sample(tex ## _sampler, coord)\n';
  329. s += '#define textureShared(tex, coord) tex.sample($sharedSampler, coord)\n';
  330. s += '#define textureLod(tex, coord, lod) tex.sample(tex ## _sampler, coord, level(lod))\n';
  331. s += '#define textureLodShared(tex, coord, lod) tex.sample($sharedSampler, coord, level(lod))\n';
  332. s += '#define texelFetch(tex, coord, lod) tex.read(uint2(coord), uint(lod))\n';
  333. s += 'float2 _getDimensions(texture2d<float> tex, uint lod) { return float2(tex.get_width(lod), tex.get_height(lod)); }\n';
  334. s += '#define textureSize _getDimensions\n';
  335. s += '#define mod(a, b) fmod(a, b)\n';
  336. s += '#define vec2 float2\n';
  337. s += '#define vec3 float3\n';
  338. s += '#define vec4 float4\n';
  339. s += '#define ivec2 int2\n';
  340. s += '#define ivec3 int3\n';
  341. s += '#define ivec4 int4\n';
  342. s += '#define mat2 float2x2\n';
  343. s += '#define mat3 float3x3\n';
  344. s += '#define mat4 float4x4\n';
  345. s += '#define dFdx dfdx\n';
  346. s += '#define dFdy dfdy\n';
  347. s += '#define inversesqrt rsqrt\n';
  348. s += '#define mul(a, b) b * a\n';
  349. s += '#define discard discard_fragment()\n';
  350. for (a in includes) {
  351. s += '#include "' + a + '"\n';
  352. }
  353. s += header;
  354. // Input structure
  355. var index = 0;
  356. //if (ins.length > 0) {
  357. s += 'struct main_in {\n';
  358. index = 0;
  359. ins.sort(function(a, b): Int {
  360. // Sort inputs by name
  361. return a.substring(4) >= b.substring(4) ? 1 : -1;
  362. });
  363. if (shader_type == 'vert') {
  364. for (a in ins) {
  365. s += '$a [[attribute($index)]];\n';
  366. index++;
  367. }
  368. }
  369. else {
  370. for (a in ins) {
  371. s += '$a [[user(locn$index)]];\n';
  372. index++;
  373. }
  374. }
  375. s += '};\n';
  376. //}
  377. // Output structure
  378. var num = 0;
  379. if (outs.length > 0 || shader_type == 'vert') {
  380. s += 'struct main_out {\n';
  381. outs.sort(function(a, b): Int {
  382. // Sort outputs by name
  383. return a.substring(4) >= b.substring(4) ? 1 : -1;
  384. });
  385. index = 0;
  386. if (shader_type == 'vert') {
  387. for (a in outs) {
  388. s += '$a [[user(locn$index)]];\n';
  389. index++;
  390. }
  391. s += 'float4 svpos [[position]];\n';
  392. }
  393. else {
  394. var out = outs[0];
  395. // Multiple render targets
  396. if (out.charAt(out.length - 1) == ']') {
  397. num = Std.parseInt(out.charAt(out.length - 2));
  398. for (i in 0...num) {
  399. s += 'float4 fragColor_$i [[color($i)]];\n';
  400. }
  401. }
  402. else {
  403. s += 'float4 fragColor [[color(0)]];\n';
  404. }
  405. }
  406. s += '};\n';
  407. }
  408. var samplers: Array<String> = [];
  409. if (uniforms.length > 0) {
  410. s += 'struct main_uniforms {\n';
  411. for (a in uniforms) {
  412. if (StringTools.startsWith(a, 'sampler')) {
  413. samplers.push(a);
  414. }
  415. else {
  416. s += a + ';\n';
  417. }
  418. }
  419. s += '};\n';
  420. }
  421. for (f in functions) {
  422. s += f + '\n';
  423. }
  424. // Begin main declaration
  425. s += '#undef texture\n';
  426. s += shader_type == 'vert' ? 'vertex ' : 'fragment ';
  427. s += (outs.length > 0 || shader_type == 'vert') ? 'main_out ' : 'void ';
  428. s += 'my_main(';
  429. //if (ins.length > 0) {
  430. s += 'main_in in [[stage_in]]';
  431. //}
  432. if (uniforms.length > 0) {
  433. var bufi = shader_type == 'vert' ? 1 : 0;
  434. s += ', constant main_uniforms& uniforms [[buffer($bufi)]]';
  435. }
  436. if (samplers.length > 0) {
  437. for (i in 0...samplers.length) {
  438. s += ', ${samplers[i]} [[texture($i)]]';
  439. s += ', sampler ' + samplers[i].split(' ')[1] + '_sampler [[sampler($i)]]';
  440. }
  441. }
  442. if (sharedSamplers.length > 0) {
  443. for (i in 0...sharedSamplers.length) {
  444. var index = samplers.length + i;
  445. s += ', ${sharedSamplers[i]} [[texture($index)]]';
  446. }
  447. s += ', sampler $sharedSampler [[sampler(${samplers.length})]]';
  448. }
  449. // Built-ins
  450. if (shader_type == 'vert' && main.indexOf("gl_VertexID") >= 0) {
  451. s += ', uint gl_VertexID [[vertex_id]]';
  452. }
  453. if (shader_type == 'vert' && main.indexOf("gl_InstanceID") >= 0) {
  454. s += ', uint gl_InstanceID [[instance_id]]';
  455. }
  456. // End main declaration
  457. s += ') {\n';
  458. s += '#define texture(tex, coord) tex.sample(tex ## _sampler, coord)\n';
  459. // Declare inputs
  460. for (a in ins) {
  461. var b = a.substring(5); // Remove type 'vec4 '
  462. s += '$a = in.$b;\n';
  463. }
  464. for (a in uniforms) {
  465. if (!StringTools.startsWith(a, 'sampler')) {
  466. var b = a.split(" ")[1]; // Remove type 'vec4 '
  467. if (b.indexOf("[") >= 0) {
  468. b = b.substring(0, b.indexOf("["));
  469. var type = a.split(" ")[0];
  470. s += 'constant $type *$b = uniforms.$b;\n';
  471. }
  472. else {
  473. s += '$a = uniforms.$b;\n';
  474. }
  475. }
  476. }
  477. if (shader_type == 'vert') {
  478. s += 'vec4 gl_Position;\n';
  479. for (a in outs) {
  480. s += '$a;\n';
  481. }
  482. }
  483. else {
  484. if (outs.length > 0) {
  485. if (num > 0) s += 'vec4 fragColor[$num];\n';
  486. else s += 'vec4 fragColor;\n';
  487. }
  488. }
  489. s += main_attribs;
  490. s += main_textures;
  491. s += main_normal;
  492. s += main_init;
  493. s += main;
  494. s += main_end;
  495. // Write output structure
  496. if (outs.length > 0 || shader_type == 'vert') {
  497. s += 'main_out out = {};\n';
  498. if (shader_type == 'vert') {
  499. s += 'gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n';
  500. s += 'out.svpos = gl_Position;\n';
  501. for (a in outs) {
  502. var b = a.split(" ")[1]; // Remove type 'vec4 '
  503. s += 'out.$b = $b;\n';
  504. }
  505. }
  506. else {
  507. if (num > 0) {
  508. for (i in 0...num) {
  509. s += 'out.fragColor_$i = fragColor[$i];\n';
  510. }
  511. }
  512. else {
  513. s += 'out.fragColor = fragColor;\n';
  514. }
  515. }
  516. s += 'return out;\n';
  517. }
  518. s += '}\n';
  519. #else // kha_opengl
  520. #if kha_vulkan
  521. var s = '#version 450\n';
  522. #elseif krom_android
  523. var s = '#version 300 es\n';
  524. if (shader_type == 'frag') {
  525. s += 'precision highp float;\n';
  526. s += 'precision mediump int;\n';
  527. }
  528. #else
  529. var s = '#version 330\n';
  530. #end
  531. s += '#define textureArg(tex) sampler2D tex\n';
  532. s += '#define texturePass(tex) tex\n';
  533. s += '#define mul(a, b) b * a\n';
  534. s += '#define textureShared texture\n';
  535. s += '#define textureLodShared textureLod\n';
  536. s += '#define atan2(x, y) atan(y, x)\n';
  537. s += header;
  538. var in_ext = '';
  539. var out_ext = '';
  540. for (a in includes) {
  541. s += '#include "' + a + '"\n';
  542. }
  543. for (a in ins) {
  544. s += 'in $a$in_ext;\n';
  545. }
  546. for (a in outs) {
  547. s += 'out $a$out_ext;\n';
  548. }
  549. for (a in uniforms) {
  550. s += 'uniform ' + a + ';\n';
  551. }
  552. for (a in sharedSamplers) {
  553. s += 'uniform ' + a + ';\n';
  554. }
  555. for (f in functions) {
  556. s += f + '\n';
  557. }
  558. s += 'void main() {\n';
  559. s += main_attribs;
  560. s += main_textures;
  561. s += main_normal;
  562. s += main_init;
  563. s += main;
  564. s += main_end;
  565. s += '}\n';
  566. #end
  567. return s;
  568. }
  569. }