ashader.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. // Simple text processing tool for converting shaders at runtime.
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6. #include "iron_string.h"
  7. #ifdef __linux__
  8. int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
  9. #endif
  10. #ifdef _WIN32
  11. #include <d3d11.h>
  12. #include <D3Dcompiler.h>
  13. static void write_attrib(char *file, int *output_len, const char *attrib, int index) {
  14. if (index > -1) {
  15. strcpy(file + (*output_len), attrib);
  16. (*output_len) += strlen(attrib);
  17. file[(*output_len)] = 0;
  18. (*output_len) += 1;
  19. file[(*output_len)] = index;
  20. (*output_len) += 1;
  21. }
  22. }
  23. char *hlsl_to_bin(char *source, char *shader_type, char *to) {
  24. char *type;
  25. if (string_equals(shader_type, "vert")) {
  26. type = "vs_5_0";
  27. }
  28. else if (string_equals(shader_type, "frag")) {
  29. type = "ps_5_0";
  30. }
  31. else {
  32. type = "gs_5_0";
  33. }
  34. ID3DBlob *error_message;
  35. ID3DBlob *shader_buffer;
  36. // UINT flags = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_SKIP_VALIDATION;
  37. UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
  38. HRESULT hr = D3DCompile(source, strlen(source) + 1, NULL, NULL, NULL, "main", type, flags, 0, &shader_buffer, &error_message);
  39. if (hr != S_OK) {
  40. printf("%s\n", (char *)error_message->lpVtbl->GetBufferPointer(error_message));
  41. return NULL;
  42. }
  43. ID3D11ShaderReflection *reflector = NULL;
  44. D3DReflect(shader_buffer->lpVtbl->GetBufferPointer(shader_buffer), shader_buffer->lpVtbl->GetBufferSize(shader_buffer), &IID_ID3D11ShaderReflection, (void **)&reflector);
  45. int len = shader_buffer->lpVtbl->GetBufferSize(shader_buffer);
  46. char *file = malloc(len * 2);
  47. int output_len = 0;
  48. bool has_bone = strstr(source, " bone:") != NULL;
  49. bool has_col = strstr(source, " col:") != NULL;
  50. bool has_nor = strstr(source, " nor:") != NULL;
  51. bool has_pos = strstr(source, " pos:") != NULL;
  52. bool has_tex = strstr(source, " tex:") != NULL;
  53. int ibone = -1;
  54. int icol = -1;
  55. int inor = -1;
  56. int ipos = -1;
  57. int itex = -1;
  58. int iweight = -1;
  59. int index = 0;
  60. if (has_bone) ibone = index++;
  61. if (has_col) icol = index++;
  62. if (has_nor) inor = index++;
  63. if (has_pos) ipos = index++;
  64. if (has_tex) itex = index++;
  65. if (has_bone) iweight = index++;
  66. file[output_len] = (char)index;
  67. output_len += 1;
  68. write_attrib(file, &output_len, "bone", ibone);
  69. write_attrib(file, &output_len, "col", icol);
  70. write_attrib(file, &output_len, "nor", inor);
  71. write_attrib(file, &output_len, "pos", ipos);
  72. write_attrib(file, &output_len, "tex", itex);
  73. write_attrib(file, &output_len, "weight", iweight);
  74. D3D11_SHADER_DESC desc;
  75. reflector->lpVtbl->GetDesc(reflector, &desc);
  76. file[output_len] = desc.BoundResources;
  77. output_len += 1;
  78. for (int i = 0; i < desc.BoundResources; ++i) {
  79. D3D11_SHADER_INPUT_BIND_DESC bindDesc;
  80. reflector->lpVtbl->GetResourceBindingDesc(reflector, i, &bindDesc);
  81. strcpy(file + output_len, bindDesc.Name);
  82. output_len += strlen(bindDesc.Name);
  83. file[output_len] = 0;
  84. output_len += 1;
  85. file[output_len] = bindDesc.BindPoint;
  86. output_len += 1;
  87. }
  88. ID3D11ShaderReflectionConstantBuffer *constants = reflector->lpVtbl->GetConstantBufferByName(reflector, "$Globals");
  89. D3D11_SHADER_BUFFER_DESC buffer_desc;
  90. hr = constants->lpVtbl->GetDesc(constants, &buffer_desc);
  91. if (hr == S_OK) {
  92. file[output_len] = buffer_desc.Variables;
  93. output_len += 1;
  94. for (int i = 0; i < buffer_desc.Variables; ++i) {
  95. ID3D11ShaderReflectionVariable *variable = constants->lpVtbl->GetVariableByIndex(constants, i);
  96. D3D11_SHADER_VARIABLE_DESC variable_desc;
  97. hr = variable->lpVtbl->GetDesc(variable, &variable_desc);
  98. if (hr == S_OK) {
  99. strcpy(file + output_len, variable_desc.Name);
  100. output_len += strlen(variable_desc.Name);
  101. file[output_len] = 0;
  102. output_len += 1;
  103. *(uint32_t *)(file + output_len) = variable_desc.StartOffset;
  104. output_len += 4;
  105. *(uint32_t *)(file + output_len) = variable_desc.Size;
  106. output_len += 4;
  107. D3D11_SHADER_TYPE_DESC type_desc;
  108. ID3D11ShaderReflectionType *type = variable->lpVtbl->GetType(variable);
  109. hr = type->lpVtbl->GetDesc(type, &type_desc);
  110. if (hr == S_OK) {
  111. file[output_len] = type_desc.Columns;
  112. output_len += 1;
  113. file[output_len] = type_desc.Rows;
  114. output_len += 1;
  115. }
  116. else {
  117. file[output_len] = 0;
  118. output_len += 1;
  119. file[output_len] = 0;
  120. output_len += 1;
  121. }
  122. }
  123. }
  124. }
  125. else {
  126. file[output_len] = 0;
  127. output_len += 1;
  128. }
  129. memcpy(file + output_len, (char *)shader_buffer->lpVtbl->GetBufferPointer(shader_buffer), shader_buffer->lpVtbl->GetBufferSize(shader_buffer));
  130. output_len += shader_buffer->lpVtbl->GetBufferSize(shader_buffer);
  131. shader_buffer->lpVtbl->Release(shader_buffer);
  132. reflector->lpVtbl->Release(reflector);
  133. FILE *fp = fopen(to, "wb");
  134. fwrite(file, 1, output_len, fp);
  135. fclose(fp);
  136. free(file);
  137. }
  138. void hlslbin(const char *from, const char *to) {
  139. FILE *fp = fopen(from, "rb");
  140. fseek(fp , 0, SEEK_END);
  141. int size = ftell(fp);
  142. rewind(fp);
  143. char *source = malloc(size + 1);
  144. source[size] = 0;
  145. fread(source, size, 1, fp);
  146. fclose(fp);
  147. char *type;
  148. if (strstr(from, ".vert.")) {
  149. type = "vert";
  150. }
  151. else if (strstr(from, ".frag.")) {
  152. type = "frag";
  153. }
  154. else {
  155. type = "geom";
  156. }
  157. hlsl_to_bin(source, type, to);
  158. }
  159. #endif
  160. static char out[128 * 1024];
  161. static int out_pos = 0;
  162. static char line[1024];
  163. static char tmp[1024];
  164. static char *buffer;
  165. static int buffer_size;
  166. static int buffer_pos = 0;
  167. typedef struct var {
  168. char name[64];
  169. char type[16];
  170. } var_t;
  171. static char defines[32][64];
  172. static int defines_count;
  173. static bool is_defined[8];
  174. static int is_defined_index;
  175. static char *numbers[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
  176. static var_t inputs[8];
  177. static var_t outputs[8];
  178. static var_t uniforms[32];
  179. static var_t samplers[32];
  180. static int inputs_count;
  181. static int outputs_count;
  182. static int uniforms_count;
  183. static int samplers_count;
  184. static char *shader_type;
  185. const char *version_glsl = "#version 450\n";
  186. const char *version_essl = "#version 300 es\n";
  187. const char *precision_essl = "precision highp float;\nprecision mediump int;\n";
  188. const char *header_glsl = "#define GLSL\n\
  189. #define mul(a, b) b * a\n\
  190. #define atan2(x, y) atan(y, x)\n\
  191. #define OUT(t, v) out t v\n\
  192. ";
  193. const char *header_hlsl = "#define HLSL\n\
  194. #define sampler2D Texture2D\n\
  195. #define sampler3D Texture3D\n\
  196. #define texture(tex, coord) tex.Sample(tex ## _sampler, coord)\n\
  197. #define textureLod(tex, coord, lod) tex.SampleLevel(tex ## _sampler, coord, lod)\n\
  198. #define texelFetch(tex, coord, lod) tex.Load(float3(coord.xy, lod))\n\
  199. uint2 _GetDimensions(Texture2D tex, uint lod) { uint x, y; tex.GetDimensions(x, y); return uint2(x, y); }\n\
  200. #define textureSize _GetDimensions\n\
  201. #define mod(a, b) (a % b)\n\
  202. #define vec2 float2\n\
  203. #define vec3 float3\n\
  204. #define vec4 float4\n\
  205. #define ivec2 int2\n\
  206. #define ivec3 int3\n\
  207. #define ivec4 int4\n\
  208. #define mat2 float2x2\n\
  209. #define mat3 float3x3\n\
  210. #define mat4 float4x4\n\
  211. #define dFdx ddx\n\
  212. #define dFdy ddy\n\
  213. #define inversesqrt rsqrt\n\
  214. #define fract frac\n\
  215. #define mix lerp\n\
  216. #define OUT(t, v) out t v\n\
  217. ";
  218. const char *header_msl = "// my_main\n\
  219. #define METAL\n\
  220. #include <metal_stdlib>\n\
  221. #include <simd/simd.h>\n\
  222. using namespace metal;\n\
  223. #define sampler2D texture2d<float>\n\
  224. #define sampler3D texture3d<float>\n\
  225. #define texture(tex, coord) tex.sample(tex ## _sampler, coord)\n\
  226. #define textureLod(tex, coord, lod) tex.sample(tex ## _sampler, coord, level(lod))\n\
  227. #define texelFetch(tex, coord, lod) tex.read(uint2(coord), uint(lod))\n\
  228. float2 _getDimensions(texture2d<float> tex, uint lod) { return float2(tex.get_width(lod), tex.get_height(lod)); }\n\
  229. #define textureSize _getDimensions\n\
  230. #define mod(a, b) fmod(a, b)\n\
  231. #define vec2 float2\n\
  232. #define vec3 float3\n\
  233. #define vec4 float4\n\
  234. #define ivec2 int2\n\
  235. #define ivec3 int3\n\
  236. #define ivec4 int4\n\
  237. #define mat2 float2x2\n\
  238. #define mat3 float3x3\n\
  239. #define mat4 float4x4\n\
  240. #define dFdx dfdx\n\
  241. #define dFdy dfdy\n\
  242. #define inversesqrt rsqrt\n\
  243. #define mul(a, b) b * a\n\
  244. #define discard discard_fragment()\n\
  245. #define OUT(t, v) thread t &v\n\
  246. class my_class {\n\
  247. public:\n\
  248. ";
  249. static char *read_line() {
  250. int i = 0;
  251. while (true) {
  252. if (buffer[buffer_pos] == '\0') {
  253. return NULL;
  254. }
  255. line[i] = buffer[buffer_pos];
  256. i++;
  257. buffer_pos++;
  258. #ifdef _WIN32
  259. if (line[i - 1] == '\r') {
  260. line[i - 1] = '\n';
  261. buffer_pos++; // Skip \n
  262. break;
  263. }
  264. #endif
  265. if (line[i - 1] == '\n') {
  266. break;
  267. }
  268. }
  269. line[i] = '\0';
  270. return &line[0];
  271. }
  272. static void w(char *str) {
  273. strcpy(out + out_pos, str);
  274. out_pos += strlen(str);
  275. }
  276. static bool is_undefined() {
  277. for (int i = 0; i <= is_defined_index; ++i) {
  278. if (!is_defined[i]) {
  279. return true;
  280. }
  281. }
  282. return false;
  283. }
  284. static void write_includes(char *file, int off) {
  285. char *_buffer = buffer;
  286. int _pos = buffer_pos;
  287. buffer_pos = off;
  288. FILE *fp = fopen(file, "rb");
  289. fseek(fp, 0, SEEK_END);
  290. int size = ftell(fp);
  291. rewind(fp);
  292. buffer = malloc(size + 1);
  293. buffer[size] = '\0';
  294. fread(buffer, size, 1, fp);
  295. fclose(fp);
  296. while (true) {
  297. char *line = read_line();
  298. if (line == NULL) {
  299. break;
  300. }
  301. if (starts_with(line, "#include ")) {
  302. char *rel = line + 10; // #include "
  303. rel[strlen(rel) - 1 - 1] = '\0'; // trailing "
  304. char tmp[512];
  305. int last = string_last_index_of(file, "/") + 1;
  306. strncpy(tmp, file, last);
  307. tmp[last] = '\0';
  308. strcat(tmp, rel);
  309. write_includes(tmp, 0);
  310. line[0] = '\0';
  311. }
  312. if (starts_with(line, "#define ")) {
  313. strcpy(defines[defines_count++], line + 8);
  314. }
  315. if (starts_with(line, "#ifdef ")) {
  316. line += 7;
  317. is_defined_index++;
  318. is_defined[is_defined_index] = false;
  319. for (int i = 0; i < defines_count; ++i) {
  320. if (string_equals(line, defines[i])) {
  321. is_defined[is_defined_index] = true;
  322. break;
  323. }
  324. }
  325. continue;
  326. }
  327. if (starts_with(line, "#else")) {
  328. is_defined[is_defined_index] = !is_defined[is_defined_index];
  329. continue;
  330. }
  331. if (starts_with(line, "#endif")) {
  332. is_defined_index--;
  333. continue;
  334. }
  335. if (starts_with(line, "//") || is_undefined()) {
  336. continue;
  337. }
  338. w(line);
  339. }
  340. free(buffer);
  341. buffer = _buffer;
  342. buffer_pos = _pos;
  343. }
  344. static void write_header(char *shader_lang) {
  345. if (string_equals(shader_lang, "glsl") ||
  346. string_equals(shader_lang, "essl") ||
  347. string_equals(shader_lang, "spirv")
  348. ) {
  349. if (string_equals(shader_lang, "essl")) {
  350. w(version_essl);
  351. w(precision_essl);
  352. }
  353. else {
  354. w(version_glsl);
  355. }
  356. w(header_glsl);
  357. if (string_equals(shader_lang, "spirv")) {
  358. strcpy(defines[defines_count++], "SPIRV\n");
  359. }
  360. else {
  361. strcpy(defines[defines_count++], "GLSL\n");
  362. if (string_equals(shader_lang, "essl")) {
  363. strcpy(defines[defines_count++], "ESSL\n");
  364. }
  365. }
  366. }
  367. else if (string_equals(shader_lang, "hlsl")) {
  368. w(header_hlsl);
  369. strcpy(defines[defines_count++], "HLSL\n");
  370. }
  371. else if (string_equals(shader_lang, "msl")) {
  372. w(header_msl);
  373. strcpy(defines[defines_count++], "METAL\n");
  374. }
  375. }
  376. static int sort_vars(const void *_a, const void *_b) {
  377. var_t *a = _a;
  378. var_t *b = _b;
  379. return strcmp(a->name, b->name);
  380. }
  381. static void read_vars(char *line, var_t *vars, int *vars_count, char *start) {
  382. *vars_count = 0;
  383. while (starts_with(line, start)) {
  384. memset(&vars[*vars_count], 0, sizeof(var_t));
  385. line = line + strlen(start);
  386. int pos = string_index_of(line, " ");
  387. strncat(vars[*vars_count].type, line, pos);
  388. line += pos + 1;
  389. pos = string_index_of(line, ";");
  390. strncat(vars[*vars_count].name, line, pos);
  391. (*vars_count)++;
  392. line = read_line();
  393. while (starts_with(line, "#")) {
  394. w(line);
  395. line = read_line();
  396. }
  397. }
  398. qsort(vars, *vars_count, sizeof(var_t), sort_vars);
  399. }
  400. static void init_buffer() {
  401. buffer = malloc(128 * 1024);
  402. strcpy(buffer, out);
  403. buffer_size = strlen(buffer);
  404. buffer_pos = 0;
  405. out[0] = '\0';
  406. out_pos = 0;
  407. inputs_count = 0;
  408. outputs_count = 0;
  409. uniforms_count = 0;
  410. samplers_count = 0;
  411. }
  412. static void write_hlsl_return() {
  413. w("\tshader_output stage_output;\n");
  414. if (string_equals(shader_type, "vert")) {
  415. w("\tgl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n");
  416. w("\tstage_output.gl_Position = gl_Position;\n");
  417. }
  418. for (int i = 0; i < outputs_count; ++i) {
  419. w("\tstage_output.");
  420. w(outputs[i].name);
  421. if (out[out_pos - 1] == ']') {
  422. out_pos -= 3; // Erase [i]
  423. }
  424. w(" = ");
  425. w(outputs[i].name);
  426. if (out[out_pos - 1] == ']') {
  427. out_pos -= 3;
  428. }
  429. w(";\n");
  430. }
  431. w("\treturn stage_output;\n");
  432. }
  433. static char *write_hlsl_inputs(char *line) {
  434. read_vars(line, inputs, &inputs_count, "in ");
  435. w("struct shader_input {\n");
  436. for (int i = 0; i < inputs_count; ++i) {
  437. w("\t");
  438. w(inputs[i].type);
  439. w(" ");
  440. w(inputs[i].name);
  441. w(": TEXCOORD");
  442. w(numbers[i]);
  443. w(";\n");
  444. }
  445. if (string_index_of(buffer, "gl_VertexID") > -1) {
  446. w("\tuint gl_VertexID: SV_VertexID;\n");
  447. }
  448. if (string_index_of(buffer, "gl_InstanceID") > -1) {
  449. w("\tuint gl_InstanceID: SV_InstanceID;\n");
  450. }
  451. w("};\n");
  452. return line;
  453. }
  454. static char *write_hlsl_outputs(char *line) {
  455. read_vars(line, outputs, &outputs_count, "out ");
  456. w("struct shader_output {\n");
  457. for (int i = 0; i < outputs_count; ++i) {
  458. w("\t");
  459. w(outputs[i].type);
  460. w(" ");
  461. w(outputs[i].name);
  462. if (string_equals(shader_type, "vert")) {
  463. w(": TEXCOORD");
  464. }
  465. else {
  466. w(": SV_TARGET");
  467. }
  468. w(numbers[i]);
  469. w(";\n");
  470. }
  471. if (string_equals(shader_type, "vert")) {
  472. w("\tvec4 gl_Position: SV_POSITION;\n");
  473. }
  474. w("};\n");
  475. return line;
  476. }
  477. static void to_hlsl() {
  478. init_buffer();
  479. while (true) {
  480. char *line = read_line();
  481. if (line == NULL) {
  482. break;
  483. }
  484. if (starts_with(line, "in ")) {
  485. line = write_hlsl_inputs(line);
  486. for (int i = 0; i < inputs_count; ++i) {
  487. w("static ");
  488. w(inputs[i].type);
  489. w(" ");
  490. w(inputs[i].name);
  491. w(";\n");
  492. }
  493. if (string_index_of(buffer, "gl_VertexID") > -1) {
  494. w("static uint gl_VertexID;\n");
  495. }
  496. if (string_index_of(buffer, "gl_InstanceID") > -1) {
  497. w("static uint gl_InstanceID;\n");
  498. }
  499. }
  500. if (starts_with(line, "out ")) {
  501. line = write_hlsl_outputs(line);
  502. if (string_equals(shader_type, "vert")) {
  503. w("static vec4 gl_Position;\n");
  504. }
  505. for (int i = 0; i < outputs_count; ++i) {
  506. w("static ");
  507. w(outputs[i].type);
  508. w(" ");
  509. w(outputs[i].name);
  510. w(";\n");
  511. }
  512. }
  513. if (starts_with(line, "uniform sampler")) {
  514. int len = strlen(line);
  515. int last = string_last_index_of(line, " ");
  516. strcpy(tmp, "SamplerState ");
  517. strncat(tmp, line + last + 1, len - last - 3); // - ";\n"
  518. strcat(tmp, "_sampler;\n");
  519. w(tmp);
  520. }
  521. if (starts_with(line, "const ")) {
  522. w("static ");
  523. }
  524. if (starts_with(line, "vec") ||
  525. starts_with(line, "float ") ||
  526. starts_with(line, "int ")
  527. ) {
  528. if (ends_with(line, ";\n")) {
  529. w("static ");
  530. }
  531. }
  532. if (ends_with(line, "return;\n")) {
  533. write_hlsl_return();
  534. line = "";
  535. }
  536. if (starts_with(line, "void main")) {
  537. w("shader_output main(shader_input stage_input) {\n");
  538. line = "";
  539. for (int i = 0; i < inputs_count; ++i) {
  540. w("\t");
  541. w(inputs[i].name);
  542. w(" = stage_input.");
  543. w(inputs[i].name);
  544. w(";\n");
  545. }
  546. if (string_index_of(buffer, "gl_VertexID") > -1) {
  547. w("\tgl_VertexID = stage_input.gl_VertexID;\n");
  548. }
  549. if (string_index_of(buffer, "gl_InstanceID") > -1) {
  550. w("\tgl_InstanceID = stage_input.gl_InstanceID;\n");
  551. }
  552. }
  553. if (starts_with(line, "}") && buffer_pos == buffer_size) {
  554. write_hlsl_return();
  555. }
  556. w(line);
  557. }
  558. free(buffer);
  559. }
  560. static char *write_msl_inputs(char *line) {
  561. read_vars(line, inputs, &inputs_count, "in ");
  562. w("struct shader_input {\n");
  563. for (int i = 0; i < inputs_count; ++i) {
  564. w("\t");
  565. w(inputs[i].type);
  566. w(" ");
  567. w(inputs[i].name);
  568. if (string_equals(shader_type, "vert")) {
  569. w(" [[attribute(");
  570. }
  571. else {
  572. w(" [[user(locn");
  573. }
  574. w(numbers[i]);
  575. w(")]];\n");
  576. }
  577. w("};\n");
  578. return line;
  579. }
  580. static char *write_msl_outputs(char *line) {
  581. read_vars(line, outputs, &outputs_count, "out ");
  582. w("struct shader_output {\n");
  583. for (int i = 0; i < outputs_count; ++i) {
  584. int pos = string_index_of(outputs[i].name, "[");
  585. if (pos > -1) {
  586. int n = outputs[i].name[pos + 1] - '0';
  587. for (int j = 0; j < n; ++j) {
  588. w("\t");
  589. w(outputs[i].type);
  590. w(" ");
  591. // w(outputs[i].name);
  592. w("frag_color");
  593. w(numbers[j]);
  594. w(" [[color(");
  595. w(numbers[j]);
  596. w(")]];\n");
  597. }
  598. }
  599. else {
  600. w("\t");
  601. w(outputs[i].type);
  602. w(" ");
  603. w(outputs[i].name);
  604. if (string_equals(shader_type, "vert")) {
  605. w(" [[user(locn");
  606. w(numbers[i]);
  607. w(")]];\n");
  608. }
  609. else {
  610. w(" [[color(0)]];\n");
  611. }
  612. }
  613. }
  614. if (string_equals(shader_type, "vert")) {
  615. w("\tvec4 gl_Position [[position]];\n");
  616. }
  617. w("};\n");
  618. return line;
  619. }
  620. static char *write_msl_uniforms(char *line) {
  621. read_vars(line, uniforms, &uniforms_count, "uniform ");
  622. w("struct shader_uniforms {\n");
  623. for (int i = 0; i < uniforms_count; ++i) {
  624. if (starts_with(uniforms[i].type, "sampler")) {
  625. strcpy(samplers[samplers_count].type, uniforms[i].type);
  626. strcpy(samplers[samplers_count].name, uniforms[i].name);
  627. samplers_count++;
  628. continue;
  629. }
  630. w("\t");
  631. w(uniforms[i].type);
  632. w(" ");
  633. w(uniforms[i].name);
  634. w(";\n");
  635. }
  636. w("};\n");
  637. return line;
  638. }
  639. static void write_msl_return() {
  640. w("\tshader_output stage_output;\n");
  641. if (string_equals(shader_type, "vert")) {
  642. w("\tgl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n");
  643. w("\tstage_output.gl_Position = gl_Position;\n");
  644. }
  645. for (int i = 0; i < outputs_count; ++i) {
  646. int pos = string_index_of(outputs[i].name, "[");
  647. if (pos > -1) {
  648. int n = outputs[i].name[pos + 1] - '0';
  649. char tmp[64];
  650. strcpy(tmp, outputs[i].name);
  651. tmp[pos] = '\0';
  652. for (int j = 0; j < n; ++j) {
  653. w("\tstage_output.");
  654. w(tmp);
  655. w(numbers[j]);
  656. w(" = ");
  657. w(tmp);
  658. w("[");
  659. w(numbers[j]);
  660. w("];\n");
  661. }
  662. }
  663. else {
  664. w("\tstage_output.");
  665. w(outputs[i].name);
  666. w(" = ");
  667. w(outputs[i].name);
  668. w(";\n");
  669. }
  670. }
  671. w("\treturn stage_output;\n");
  672. }
  673. static void to_msl() {
  674. init_buffer();
  675. char main_header[1024];
  676. char main_body[1024];
  677. strcpy(main_header, "#undef texture\n");
  678. strcpy(main_body, "\tmy_class c;\n\treturn c.my_main(stage_input");
  679. while (true) {
  680. char *line = read_line();
  681. if (line == NULL) {
  682. break;
  683. }
  684. if (starts_with(line, "in ")) {
  685. line = write_msl_inputs(line);
  686. for (int i = 0; i < inputs_count; ++i) {
  687. w(inputs[i].type);
  688. w(" ");
  689. w(inputs[i].name);
  690. w(";\n");
  691. }
  692. if (string_index_of(buffer, "gl_VertexID") > -1) {
  693. w("uint gl_VertexID;\n");
  694. }
  695. if (string_index_of(buffer, "gl_InstanceID") > -1) {
  696. w("uint gl_InstanceID;\n");
  697. }
  698. }
  699. if (starts_with(line, "out ")) {
  700. line = write_msl_outputs(line);
  701. if (string_equals(shader_type, "vert")) {
  702. w("vec4 gl_Position;\n");
  703. }
  704. for (int i = 0; i < outputs_count; ++i) {
  705. w(outputs[i].type);
  706. w(" ");
  707. w(outputs[i].name);
  708. w(";\n");
  709. }
  710. }
  711. if (starts_with(line, "uniform ")) {
  712. line = write_msl_uniforms(line);
  713. for (int i = 0; i < uniforms_count; ++i) {
  714. w(uniforms[i].type);
  715. w(" ");
  716. w(uniforms[i].name);
  717. w(";\n");
  718. if (starts_with(uniforms[i].type, "sampler")) {
  719. w("sampler ");
  720. w(uniforms[i].name);
  721. w("_sampler;\n");
  722. }
  723. }
  724. }
  725. if (starts_with(line, "void main")) {
  726. if (string_equals(shader_type, "vert")) {
  727. strcat(main_header, "vertex ");
  728. }
  729. else {
  730. strcat(main_header, "fragment ");
  731. }
  732. w("shader_output my_main(shader_input stage_input");
  733. strcat(main_header, "my_class::shader_output my_main(my_class::shader_input stage_input [[stage_in]]");
  734. if (uniforms_count > 0) {
  735. w(", constant shader_uniforms& uniforms");
  736. strcat(main_header, ", constant my_class::shader_uniforms& uniforms [[buffer(");
  737. if (string_equals(shader_type, "vert")) {
  738. strcat(main_header, "1");
  739. }
  740. else {
  741. strcat(main_header, "0");
  742. }
  743. strcat(main_header, ")]]");
  744. strcat(main_body, ", uniforms");
  745. }
  746. if (samplers_count > 0) {
  747. for (int i = 0; i < samplers_count; ++i) {
  748. w(", ");
  749. w(samplers[i].type);
  750. w(" ");
  751. w(samplers[i].name);
  752. w(", sampler ");
  753. w(samplers[i].name);
  754. w("_sampler");
  755. strcat(main_header, ", ");
  756. strcat(main_header, samplers[i].type);
  757. strcat(main_header, " ");
  758. strcat(main_header, samplers[i].name);
  759. strcat(main_header, " [[texture(");
  760. strcat(main_header, numbers[i]);
  761. strcat(main_header, ")]]");
  762. strcat(main_header, ", sampler ");
  763. strcat(main_header, samplers[i].name);
  764. strcat(main_header, "_sampler [[sampler(");
  765. strcat(main_header, numbers[i]);
  766. strcat(main_header, ")]]");
  767. strcat(main_body, ", ");
  768. strcat(main_body, samplers[i].name);
  769. strcat(main_body, ", ");
  770. strcat(main_body, samplers[i].name);
  771. strcat(main_body, "_sampler");
  772. }
  773. }
  774. if (string_equals(shader_type, "vert")) {
  775. if (string_index_of(buffer, "gl_VertexID") > -1) {
  776. w(", uint gl_VertexID");
  777. strcat(main_header, ", uint gl_VertexID [[vertex_id]]");
  778. strcat(main_body, ", gl_VertexID");
  779. }
  780. if (string_index_of(buffer, "gl_InstanceID") > -1) {
  781. w(", uint gl_InstanceID");
  782. strcat(main_header, ", uint gl_InstanceID [[instance_id]]");
  783. strcat(main_body, ", gl_InstanceID");
  784. }
  785. }
  786. w(") {\n");
  787. strcat(main_header, ") {\n");
  788. strcat(main_body, ");\n}\n");
  789. line = "";
  790. for (int i = 0; i < inputs_count; ++i) {
  791. w("\t");
  792. w(inputs[i].name);
  793. w(" = stage_input.");
  794. w(inputs[i].name);
  795. w(";\n");
  796. }
  797. if (string_index_of(buffer, "gl_VertexID") > -1) {
  798. w("\tthis->gl_VertexID = gl_VertexID;\n");
  799. }
  800. if (string_index_of(buffer, "gl_InstanceID") > -1) {
  801. w("\tthis->gl_InstanceID = gl_InstanceID;\n");
  802. }
  803. for (int i = 0; i < uniforms_count; ++i) {
  804. int pos = string_index_of(uniforms[i].name, "[");
  805. if (pos > -1) {
  806. char tmp[64];
  807. strcpy(tmp, uniforms[i].name);
  808. tmp[pos] = '\0';
  809. int n = uniforms[i].name[pos + 1] - '0';
  810. for (int j = 0; j < n; ++j) {
  811. w("\tthis->");
  812. w(tmp);
  813. w("[");
  814. w(numbers[j]);
  815. w("] = uniforms.");
  816. w(tmp);
  817. w("[");
  818. w(numbers[j]);
  819. w("];\n");
  820. }
  821. }
  822. else if (starts_with(uniforms[i].type, "sampler")) {
  823. w("\tthis->");
  824. w(uniforms[i].name);
  825. w(" = ");
  826. w(uniforms[i].name);
  827. w(";\n");
  828. w("\tthis->");
  829. w(uniforms[i].name);
  830. w("_sampler = ");
  831. w(uniforms[i].name);
  832. w("_sampler;\n");
  833. }
  834. else {
  835. w("\tthis->");
  836. w(uniforms[i].name);
  837. w(" = uniforms.");
  838. w(uniforms[i].name);
  839. w(";\n");
  840. }
  841. }
  842. }
  843. if (starts_with(line, "}") && buffer_pos == buffer_size) {
  844. write_msl_return();
  845. }
  846. w(line);
  847. }
  848. w("};\n"); // class my_class
  849. w(main_header);
  850. w(main_body);
  851. free(buffer);
  852. }
  853. int ashader(char *shader_lang, char *from, char *to) {
  854. // shader_lang == glsl || essl || hlsl || msl || spirv
  855. shader_type = string_index_of(from, ".vert") != -1 ? "vert" : "frag";
  856. #ifdef _WIN32
  857. char from_[512];
  858. strcpy(from_, from);
  859. int len = strlen(from_);
  860. for (int i = 0; i < len; ++i) {
  861. if (from_[i] == '\\') {
  862. from_[i] = '/';
  863. }
  864. }
  865. from = from_;
  866. #endif
  867. out[0] = '\0';
  868. out_pos = 0;
  869. defines_count = 0;
  870. is_defined[0] = true;
  871. is_defined_index = 0;
  872. write_header(shader_lang);
  873. write_includes(from, 13); // Skip #version 450\n
  874. if (string_equals(shader_lang, "glsl") ||
  875. string_equals(shader_lang, "essl")
  876. ) {
  877. FILE *fp = fopen(to, "wb");
  878. fwrite(out, 1, strlen(out), fp);
  879. fclose(fp);
  880. }
  881. #ifdef __linux__
  882. else if (string_equals(shader_lang, "spirv")) {
  883. char *buf = malloc(1024 * 1024);
  884. int buf_len;
  885. krafix_compile(out, buf, &buf_len, "spirv", "linux", shader_type, -1);
  886. FILE *fp = fopen(to, "wb");
  887. fwrite(buf, 1, buf_len, fp);
  888. fclose(fp);
  889. }
  890. #endif
  891. else if (string_equals(shader_lang, "hlsl")) {
  892. to_hlsl();
  893. // FILE *fp = fopen(to, "wb");
  894. // fwrite(out, 1, strlen(out), fp); // Write .hlsl
  895. // fclose(fp);
  896. #ifdef _WIN32
  897. char to_[512];
  898. strcpy(to_, to);
  899. to_[strlen(to_) - 4] = '\0';
  900. strcat(to_, "d3d11");
  901. hlsl_to_bin(out, shader_type, to_);
  902. #endif
  903. }
  904. else if (string_equals(shader_lang, "msl")) {
  905. to_msl();
  906. char to_[512];
  907. strcpy(to_, to);
  908. to_[strlen(to_) - 3] = '\0';
  909. strcat(to_, "metal");
  910. FILE *fp = fopen(to_, "wb");
  911. fwrite(out, 1, strlen(out), fp);
  912. fclose(fp);
  913. }
  914. return 0;
  915. }