gl-shaderparser.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /******************************************************************************
  2. Copyright (C) 2023 by Lain Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include "gl-subsystem.h"
  15. #include "gl-shaderparser.h"
  16. static void gl_write_function_contents(struct gl_shader_parser *glsp, struct cf_token **p_token, const char *end);
  17. static inline struct shader_var *sp_getparam(struct gl_shader_parser *glsp, struct cf_token *token)
  18. {
  19. size_t i;
  20. for (i = 0; i < glsp->parser.params.num; i++) {
  21. struct shader_var *param = glsp->parser.params.array + i;
  22. if (strref_cmp(&token->str, param->name) == 0)
  23. return param;
  24. }
  25. return NULL;
  26. }
  27. static inline size_t sp_getsampler(struct gl_shader_parser *glsp, struct cf_token *token)
  28. {
  29. size_t i;
  30. for (i = 0; i < glsp->parser.samplers.num; i++) {
  31. struct shader_sampler *sampler = glsp->parser.samplers.array + i;
  32. if (strref_cmp(&token->str, sampler->name) == 0)
  33. return i;
  34. }
  35. return -1;
  36. }
  37. static inline int cmp_type(const char *name, const size_t name_len, const char *type, const size_t type_len)
  38. {
  39. size_t min_len = (name_len < type_len) ? type_len : name_len;
  40. return astrcmp_n(name, type, min_len);
  41. }
  42. static bool gl_write_type_n(struct gl_shader_parser *glsp, const char *type, size_t len)
  43. {
  44. if (cmp_type(type, len, "float2", 6) == 0)
  45. dstr_cat(&glsp->gl_string, "vec2");
  46. else if (cmp_type(type, len, "float3", 6) == 0)
  47. dstr_cat(&glsp->gl_string, "vec3");
  48. else if (cmp_type(type, len, "float4", 6) == 0)
  49. dstr_cat(&glsp->gl_string, "vec4");
  50. else if (cmp_type(type, len, "int2", 4) == 0)
  51. dstr_cat(&glsp->gl_string, "ivec2");
  52. else if (cmp_type(type, len, "int3", 4) == 0)
  53. dstr_cat(&glsp->gl_string, "ivec3");
  54. else if (cmp_type(type, len, "int4", 4) == 0)
  55. dstr_cat(&glsp->gl_string, "ivec4");
  56. else if (cmp_type(type, len, "uint2", 5) == 0)
  57. dstr_cat(&glsp->gl_string, "uvec2");
  58. else if (cmp_type(type, len, "uint3", 5) == 0)
  59. dstr_cat(&glsp->gl_string, "uvec3");
  60. else if (cmp_type(type, len, "uint4", 5) == 0)
  61. dstr_cat(&glsp->gl_string, "uvec4");
  62. else if (cmp_type(type, len, "float3x3", 8) == 0)
  63. dstr_cat(&glsp->gl_string, "mat3x3");
  64. else if (cmp_type(type, len, "float3x4", 8) == 0)
  65. dstr_cat(&glsp->gl_string, "mat3x4");
  66. else if (cmp_type(type, len, "float4x4", 8) == 0)
  67. dstr_cat(&glsp->gl_string, "mat4x4");
  68. else if (cmp_type(type, len, "texture2d", 9) == 0)
  69. dstr_cat(&glsp->gl_string, "sampler2D");
  70. else if (cmp_type(type, len, "texture3d", 9) == 0)
  71. dstr_cat(&glsp->gl_string, "sampler3D");
  72. else if (cmp_type(type, len, "texture_cube", 12) == 0)
  73. dstr_cat(&glsp->gl_string, "samplerCube");
  74. else if (cmp_type(type, len, "texture_rect", 12) == 0)
  75. dstr_cat(&glsp->gl_string, "sampler2DRect");
  76. else
  77. return false;
  78. return true;
  79. }
  80. static inline void gl_write_type(struct gl_shader_parser *glsp, const char *type)
  81. {
  82. if (!gl_write_type_n(glsp, type, strlen(type)))
  83. dstr_cat(&glsp->gl_string, type);
  84. }
  85. static inline bool gl_write_type_token(struct gl_shader_parser *glsp, struct cf_token *token)
  86. {
  87. return gl_write_type_n(glsp, token->str.array, token->str.len);
  88. }
  89. static void gl_write_var(struct gl_shader_parser *glsp, struct shader_var *var)
  90. {
  91. if (var->var_type == SHADER_VAR_UNIFORM)
  92. dstr_cat(&glsp->gl_string, "uniform ");
  93. else if (var->var_type == SHADER_VAR_CONST)
  94. dstr_cat(&glsp->gl_string, "const ");
  95. else if (var->var_type == SHADER_VAR_INOUT)
  96. dstr_cat(&glsp->gl_string, "inout ");
  97. else if (var->var_type == SHADER_VAR_OUT)
  98. dstr_cat(&glsp->gl_string, "out ");
  99. gl_write_type(glsp, var->type);
  100. dstr_cat(&glsp->gl_string, " ");
  101. dstr_cat(&glsp->gl_string, var->name);
  102. }
  103. static inline void gl_write_params(struct gl_shader_parser *glsp)
  104. {
  105. size_t i;
  106. for (i = 0; i < glsp->parser.params.num; i++) {
  107. struct shader_var *var = glsp->parser.params.array + i;
  108. gl_write_var(glsp, var);
  109. dstr_cat(&glsp->gl_string, ";\n");
  110. }
  111. dstr_cat(&glsp->gl_string, "\n");
  112. }
  113. static void gl_write_storage_var(struct gl_shader_parser *glsp, struct shader_var *var, bool input, const char *prefix);
  114. /* unwraps a structure that's used for input/output */
  115. static void gl_unwrap_storage_struct(struct gl_shader_parser *glsp, struct shader_struct *st, const char *name,
  116. bool input, const char *prefix)
  117. {
  118. struct dstr prefix_str;
  119. size_t i;
  120. dstr_init(&prefix_str);
  121. if (prefix)
  122. dstr_copy(&prefix_str, prefix);
  123. dstr_cat(&prefix_str, name);
  124. dstr_cat(&prefix_str, "_");
  125. for (i = 0; i < st->vars.num; i++) {
  126. struct shader_var *st_var = st->vars.array + i;
  127. gl_write_storage_var(glsp, st_var, input, prefix_str.array);
  128. }
  129. dstr_free(&prefix_str);
  130. }
  131. static void gl_write_storage_var(struct gl_shader_parser *glsp, struct shader_var *var, bool input, const char *prefix)
  132. {
  133. struct shader_struct *st = shader_parser_getstruct(&glsp->parser, var->type);
  134. if (st) {
  135. gl_unwrap_storage_struct(glsp, st, var->name, input, prefix);
  136. } else {
  137. if (input && (strcmp(var->mapping, "VERTEXID") == 0))
  138. return;
  139. if (strcmp(var->mapping, "POSITION") == 0) {
  140. if (!input && (glsp->type == GS_SHADER_VERTEX))
  141. return;
  142. if (input && (glsp->type == GS_SHADER_PIXEL))
  143. return;
  144. }
  145. struct gl_parser_attrib attrib;
  146. gl_parser_attrib_init(&attrib);
  147. dstr_cat(&glsp->gl_string, input ? "in " : "out ");
  148. if (prefix)
  149. dstr_cat(&attrib.name, prefix);
  150. dstr_cat(&attrib.name, var->name);
  151. gl_write_type(glsp, var->type);
  152. dstr_cat(&glsp->gl_string, " ");
  153. dstr_cat_dstr(&glsp->gl_string, &attrib.name);
  154. dstr_cat(&glsp->gl_string, ";\n");
  155. attrib.input = input;
  156. attrib.mapping = var->mapping;
  157. da_push_back(glsp->attribs, &attrib);
  158. }
  159. }
  160. static inline void gl_write_inputs(struct gl_shader_parser *glsp, struct shader_func *main)
  161. {
  162. size_t i;
  163. for (i = 0; i < main->params.num; i++)
  164. gl_write_storage_var(glsp, main->params.array + i, true, "inputval_");
  165. dstr_cat(&glsp->gl_string, "\n");
  166. }
  167. static void gl_write_outputs(struct gl_shader_parser *glsp, struct shader_func *main)
  168. {
  169. struct shader_var var = {0};
  170. var.type = main->return_type;
  171. var.name = "outputval";
  172. if (main->mapping)
  173. var.mapping = main->mapping;
  174. gl_write_storage_var(glsp, &var, false, NULL);
  175. dstr_cat(&glsp->gl_string, "\n");
  176. }
  177. static void gl_write_struct(struct gl_shader_parser *glsp, struct shader_struct *st)
  178. {
  179. size_t i;
  180. dstr_cat(&glsp->gl_string, "struct ");
  181. dstr_cat(&glsp->gl_string, st->name);
  182. dstr_cat(&glsp->gl_string, " {\n");
  183. for (i = 0; i < st->vars.num; i++) {
  184. struct shader_var *var = st->vars.array + i;
  185. dstr_cat(&glsp->gl_string, "\t");
  186. gl_write_var(glsp, var);
  187. dstr_cat(&glsp->gl_string, ";\n");
  188. }
  189. dstr_cat(&glsp->gl_string, "};\n\n");
  190. }
  191. static void gl_write_interface_block(struct gl_shader_parser *glsp)
  192. {
  193. if (glsp->type == GS_SHADER_VERTEX) {
  194. dstr_cat(&glsp->gl_string, "out gl_PerVertex {\n"
  195. "\tvec4 gl_Position;\n};\n\n");
  196. }
  197. }
  198. static inline void gl_write_structs(struct gl_shader_parser *glsp)
  199. {
  200. size_t i;
  201. for (i = 0; i < glsp->parser.structs.num; i++) {
  202. struct shader_struct *st = glsp->parser.structs.array + i;
  203. gl_write_struct(glsp, st);
  204. }
  205. }
  206. /*
  207. * NOTE: HLSL-> GLSL intrinsic conversions
  208. * atan2 -> atan
  209. * clip -> (unsupported)
  210. * ddx -> dFdx
  211. * ddy -> dFdy
  212. * fmod -> mod (XXX: these are different if sign is negative)
  213. * frac -> fract
  214. * lerp -> mix
  215. * lit -> (unsupported)
  216. * log10 -> (unsupported)
  217. * mad -> (change to operator) [fma needs GLSL 400]
  218. * mul -> (change to operator)
  219. * rsqrt -> inversesqrt
  220. * saturate -> (use clamp)
  221. * sincos -> (map to manual sin/cos calls)
  222. * tex* -> texture
  223. * tex*grad -> textureGrad
  224. * tex*lod -> textureLod
  225. * tex*bias -> (use optional 'bias' value)
  226. * tex*proj -> textureProj
  227. *
  228. * All else can be left as-is
  229. */
  230. static bool gl_write_mad(struct gl_shader_parser *glsp, struct cf_token **p_token)
  231. {
  232. struct cf_parser *cfp = &glsp->parser.cfp;
  233. cfp->cur_token = *p_token;
  234. if (!cf_next_token(cfp))
  235. return false;
  236. if (!cf_token_is(cfp, "("))
  237. return false;
  238. dstr_cat(&glsp->gl_string, "(");
  239. gl_write_function_contents(glsp, &cfp->cur_token, ",");
  240. dstr_cat(&glsp->gl_string, ") * (");
  241. cf_next_token(cfp);
  242. gl_write_function_contents(glsp, &cfp->cur_token, ",");
  243. dstr_cat(&glsp->gl_string, ") + (");
  244. cf_next_token(cfp);
  245. gl_write_function_contents(glsp, &cfp->cur_token, ")");
  246. dstr_cat(&glsp->gl_string, "))");
  247. *p_token = cfp->cur_token;
  248. return true;
  249. }
  250. static bool gl_write_mul(struct gl_shader_parser *glsp, struct cf_token **p_token)
  251. {
  252. struct cf_parser *cfp = &glsp->parser.cfp;
  253. cfp->cur_token = *p_token;
  254. if (!cf_next_token(cfp))
  255. return false;
  256. if (!cf_token_is(cfp, "("))
  257. return false;
  258. dstr_cat(&glsp->gl_string, "(");
  259. gl_write_function_contents(glsp, &cfp->cur_token, ",");
  260. dstr_cat(&glsp->gl_string, ") * (");
  261. cf_next_token(cfp);
  262. gl_write_function_contents(glsp, &cfp->cur_token, ")");
  263. dstr_cat(&glsp->gl_string, "))");
  264. *p_token = cfp->cur_token;
  265. return true;
  266. }
  267. static bool gl_write_sincos(struct gl_shader_parser *glsp, struct cf_token **p_token)
  268. {
  269. struct cf_parser *cfp = &glsp->parser.cfp;
  270. struct dstr var = {0};
  271. bool success = false;
  272. cfp->cur_token = *p_token;
  273. if (!cf_next_token(cfp))
  274. return false;
  275. if (!cf_token_is(cfp, "("))
  276. return false;
  277. dstr_printf(&var, "sincos_var_internal_%d", glsp->sincos_counter++);
  278. dstr_cat(&glsp->gl_string, "float ");
  279. dstr_cat_dstr(&glsp->gl_string, &var);
  280. dstr_cat(&glsp->gl_string, " = ");
  281. gl_write_function_contents(glsp, &cfp->cur_token, ",");
  282. dstr_cat(&glsp->gl_string, "); ");
  283. if (!cf_next_token(cfp))
  284. goto fail;
  285. gl_write_function_contents(glsp, &cfp->cur_token, ",");
  286. dstr_cat(&glsp->gl_string, " = sin(");
  287. dstr_cat_dstr(&glsp->gl_string, &var);
  288. dstr_cat(&glsp->gl_string, "); ");
  289. if (!cf_next_token(cfp))
  290. goto fail;
  291. gl_write_function_contents(glsp, &cfp->cur_token, ")");
  292. dstr_cat(&glsp->gl_string, " = cos(");
  293. dstr_cat_dstr(&glsp->gl_string, &var);
  294. dstr_cat(&glsp->gl_string, ")");
  295. success = true;
  296. fail:
  297. dstr_free(&var);
  298. *p_token = cfp->cur_token;
  299. return success;
  300. }
  301. static bool gl_write_saturate(struct gl_shader_parser *glsp, struct cf_token **p_token)
  302. {
  303. struct cf_parser *cfp = &glsp->parser.cfp;
  304. cfp->cur_token = *p_token;
  305. if (!cf_next_token(cfp))
  306. return false;
  307. if (!cf_token_is(cfp, "("))
  308. return false;
  309. dstr_cat(&glsp->gl_string, "clamp");
  310. gl_write_function_contents(glsp, &cfp->cur_token, ")");
  311. dstr_cat(&glsp->gl_string, ", 0.0, 1.0)");
  312. *p_token = cfp->cur_token;
  313. return true;
  314. }
  315. static inline bool gl_write_texture_call(struct gl_shader_parser *glsp, struct shader_var *var, const char *call,
  316. bool sampler)
  317. {
  318. struct cf_parser *cfp = &glsp->parser.cfp;
  319. if (!cf_next_token(cfp))
  320. return false;
  321. if (!cf_token_is(cfp, "("))
  322. return false;
  323. if (sampler) {
  324. if (!cf_next_token(cfp))
  325. return false;
  326. const size_t sampler_id = sp_getsampler(glsp, cfp->cur_token);
  327. if (sampler_id == (size_t)-1)
  328. return false;
  329. if (!cf_next_token(cfp))
  330. return false;
  331. if (!cf_token_is(cfp, ","))
  332. return false;
  333. var->gl_sampler_id = sampler_id;
  334. }
  335. dstr_cat(&glsp->gl_string, call);
  336. dstr_cat(&glsp->gl_string, "(");
  337. dstr_cat(&glsp->gl_string, var->name);
  338. dstr_cat(&glsp->gl_string, ", ");
  339. return true;
  340. }
  341. /* processes texture.Sample(sampler, texcoord) */
  342. static bool gl_write_texture_code(struct gl_shader_parser *glsp, struct cf_token **p_token, struct shader_var *var)
  343. {
  344. struct cf_parser *cfp = &glsp->parser.cfp;
  345. bool written = false;
  346. cfp->cur_token = *p_token;
  347. if (!cf_next_token(cfp))
  348. return false;
  349. if (!cf_token_is(cfp, "."))
  350. return false;
  351. if (!cf_next_token(cfp))
  352. return false;
  353. const char *function_end = ")";
  354. if (cf_token_is(cfp, "Sample")) {
  355. written = gl_write_texture_call(glsp, var, "texture", true);
  356. } else if (cf_token_is(cfp, "SampleBias")) {
  357. written = gl_write_texture_call(glsp, var, "texture", true);
  358. } else if (cf_token_is(cfp, "SampleGrad")) {
  359. written = gl_write_texture_call(glsp, var, "textureGrad", true);
  360. } else if (cf_token_is(cfp, "SampleLevel")) {
  361. written = gl_write_texture_call(glsp, var, "textureLod", true);
  362. } else if (cf_token_is(cfp, "Load")) {
  363. const char *const func = (strcmp(var->type, "texture3d") == 0) ? "obs_load_3d" : "obs_load_2d";
  364. written = gl_write_texture_call(glsp, var, func, false);
  365. }
  366. if (!written)
  367. return false;
  368. if (!cf_next_token(cfp))
  369. return false;
  370. gl_write_function_contents(glsp, &cfp->cur_token, ")");
  371. dstr_cat(&glsp->gl_string, function_end);
  372. *p_token = cfp->cur_token;
  373. return true;
  374. }
  375. static bool gl_write_intrinsic(struct gl_shader_parser *glsp, struct cf_token **p_token)
  376. {
  377. struct cf_token *token = *p_token;
  378. bool written = true;
  379. if (strref_cmp(&token->str, "atan2") == 0) {
  380. dstr_cat(&glsp->gl_string, "atan");
  381. } else if (strref_cmp(&token->str, "ddx") == 0) {
  382. dstr_cat(&glsp->gl_string, "dFdx");
  383. } else if (strref_cmp(&token->str, "ddy") == 0) {
  384. dstr_cat(&glsp->gl_string, "dFdy");
  385. } else if (strref_cmp(&token->str, "fmod") == 0) {
  386. dstr_cat(&glsp->gl_string, "mod");
  387. } else if (strref_cmp(&token->str, "frac") == 0) {
  388. dstr_cat(&glsp->gl_string, "fract");
  389. } else if (strref_cmp(&token->str, "lerp") == 0) {
  390. dstr_cat(&glsp->gl_string, "mix");
  391. } else if (strref_cmp(&token->str, "mad") == 0) {
  392. /* fma not available in GLSL 330 */
  393. written = gl_write_mad(glsp, &token);
  394. } else if (strref_cmp(&token->str, "mul") == 0) {
  395. written = gl_write_mul(glsp, &token);
  396. } else if (strref_cmp(&token->str, "rsqrt") == 0) {
  397. dstr_cat(&glsp->gl_string, "inversesqrt");
  398. } else if (strref_cmp(&token->str, "saturate") == 0) {
  399. written = gl_write_saturate(glsp, &token);
  400. } else if (strref_cmp(&token->str, "sincos") == 0) {
  401. written = gl_write_sincos(glsp, &token);
  402. } else {
  403. struct shader_var *var = sp_getparam(glsp, token);
  404. if (var && astrcmp_n(var->type, "texture", 7) == 0)
  405. written = gl_write_texture_code(glsp, &token, var);
  406. else
  407. written = false;
  408. }
  409. if (written)
  410. *p_token = token;
  411. return written;
  412. }
  413. static void gl_write_function_contents(struct gl_shader_parser *glsp, struct cf_token **p_token, const char *end)
  414. {
  415. struct cf_token *token = *p_token;
  416. if (token->type != CFTOKEN_NAME || (!gl_write_type_token(glsp, token) && !gl_write_intrinsic(glsp, &token)))
  417. dstr_cat_strref(&glsp->gl_string, &token->str);
  418. while (token->type != CFTOKEN_NONE) {
  419. token++;
  420. if (end && strref_cmp(&token->str, end) == 0)
  421. break;
  422. if (token->type == CFTOKEN_NAME) {
  423. if (!gl_write_type_token(glsp, token) && !gl_write_intrinsic(glsp, &token))
  424. dstr_cat_strref(&glsp->gl_string, &token->str);
  425. } else if (token->type == CFTOKEN_OTHER) {
  426. if (*token->str.array == '{')
  427. gl_write_function_contents(glsp, &token, "}");
  428. else if (*token->str.array == '(')
  429. gl_write_function_contents(glsp, &token, ")");
  430. dstr_cat_strref(&glsp->gl_string, &token->str);
  431. } else {
  432. dstr_cat_strref(&glsp->gl_string, &token->str);
  433. }
  434. }
  435. *p_token = token;
  436. }
  437. static void gl_write_function(struct gl_shader_parser *glsp, struct shader_func *func)
  438. {
  439. size_t i;
  440. struct cf_token *token;
  441. gl_write_type(glsp, func->return_type);
  442. dstr_cat(&glsp->gl_string, " ");
  443. if (strcmp(func->name, "main") == 0)
  444. dstr_cat(&glsp->gl_string, "_main_wrap");
  445. else
  446. dstr_cat(&glsp->gl_string, func->name);
  447. dstr_cat(&glsp->gl_string, "(");
  448. for (i = 0; i < func->params.num; i++) {
  449. struct shader_var *param = func->params.array + i;
  450. if (i > 0)
  451. dstr_cat(&glsp->gl_string, ", ");
  452. gl_write_var(glsp, param);
  453. }
  454. dstr_cat(&glsp->gl_string, ")\n");
  455. token = func->start;
  456. gl_write_function_contents(glsp, &token, "}");
  457. dstr_cat(&glsp->gl_string, "}\n\n");
  458. }
  459. static inline void gl_write_functions(struct gl_shader_parser *glsp)
  460. {
  461. size_t i;
  462. for (i = 0; i < glsp->parser.funcs.num; i++) {
  463. struct shader_func *func = glsp->parser.funcs.array + i;
  464. gl_write_function(glsp, func);
  465. }
  466. }
  467. static inline void gl_write_main_interface_assign(struct gl_shader_parser *glsp, struct shader_var *var,
  468. const char *src)
  469. {
  470. /* vertex shaders: write gl_Position */
  471. if (glsp->type == GS_SHADER_VERTEX && strcmp(var->mapping, "POSITION") == 0) {
  472. dstr_cat(&glsp->gl_string, "\tgl_Position = ");
  473. dstr_cat(&glsp->gl_string, src);
  474. dstr_cat(&glsp->gl_string, var->name);
  475. dstr_cat(&glsp->gl_string, ";\n");
  476. }
  477. }
  478. static void gl_write_main_storage_assign(struct gl_shader_parser *glsp, struct shader_var *var, const char *dst,
  479. const char *src, bool input)
  480. {
  481. struct shader_struct *st;
  482. struct dstr dst_copy = {0};
  483. char ch_left = input ? '.' : '_';
  484. char ch_right = input ? '_' : '.';
  485. if (dst) {
  486. dstr_copy(&dst_copy, dst);
  487. dstr_cat_ch(&dst_copy, ch_left);
  488. } else {
  489. dstr_copy(&dst_copy, "\t");
  490. }
  491. dstr_cat(&dst_copy, var->name);
  492. st = shader_parser_getstruct(&glsp->parser, var->type);
  493. if (st) {
  494. struct dstr src_copy = {0};
  495. size_t i;
  496. if (src)
  497. dstr_copy(&src_copy, src);
  498. dstr_cat(&src_copy, var->name);
  499. dstr_cat_ch(&src_copy, ch_right);
  500. for (i = 0; i < st->vars.num; i++) {
  501. struct shader_var *st_var = st->vars.array + i;
  502. gl_write_main_storage_assign(glsp, st_var, dst_copy.array, src_copy.array, input);
  503. }
  504. dstr_free(&src_copy);
  505. } else {
  506. if (input || (glsp->type != GS_SHADER_VERTEX) || (strcmp(var->mapping, "POSITION"))) {
  507. if (!dstr_is_empty(&dst_copy))
  508. dstr_cat_dstr(&glsp->gl_string, &dst_copy);
  509. dstr_cat(&glsp->gl_string, " = ");
  510. if (input && (strcmp(var->mapping, "VERTEXID") == 0))
  511. dstr_cat(&glsp->gl_string, "uint(gl_VertexID)");
  512. else if (input && (glsp->type == GS_SHADER_PIXEL) && (strcmp(var->mapping, "POSITION") == 0))
  513. dstr_cat(&glsp->gl_string, "gl_FragCoord");
  514. else {
  515. if (src)
  516. dstr_cat(&glsp->gl_string, src);
  517. dstr_cat(&glsp->gl_string, var->name);
  518. }
  519. dstr_cat(&glsp->gl_string, ";\n");
  520. }
  521. if (!input)
  522. gl_write_main_interface_assign(glsp, var, src);
  523. }
  524. dstr_free(&dst_copy);
  525. }
  526. static inline void gl_write_main_storage_inputs(struct gl_shader_parser *glsp, struct shader_func *main)
  527. {
  528. gl_write_main_storage_assign(glsp, main->params.array, NULL, "inputval_", true);
  529. }
  530. static inline void gl_write_main_storage_outputs(struct gl_shader_parser *glsp, struct shader_func *main)
  531. {
  532. /* we only do this *if* we're writing a struct, because otherwise
  533. * the call to 'main' already does the assignment for us */
  534. if (!main->mapping) {
  535. struct shader_var var = {0};
  536. var.name = "outputval";
  537. var.type = main->return_type;
  538. dstr_cat(&glsp->gl_string, "\n");
  539. gl_write_main_storage_assign(glsp, &var, NULL, NULL, false);
  540. }
  541. }
  542. static inline void gl_write_main_vars(struct gl_shader_parser *glsp, struct shader_func *main_func)
  543. {
  544. size_t i;
  545. for (i = 0; i < main_func->params.num; i++) {
  546. dstr_cat(&glsp->gl_string, "\t");
  547. dstr_cat(&glsp->gl_string, main_func->params.array[i].type);
  548. dstr_cat(&glsp->gl_string, " ");
  549. dstr_cat(&glsp->gl_string, main_func->params.array[i].name);
  550. dstr_cat(&glsp->gl_string, ";\n");
  551. }
  552. if (!main_func->mapping) {
  553. dstr_cat(&glsp->gl_string, "\t");
  554. dstr_cat(&glsp->gl_string, main_func->return_type);
  555. dstr_cat(&glsp->gl_string, " outputval;\n\n");
  556. }
  557. }
  558. static inline void gl_write_main_func_call(struct gl_shader_parser *glsp, struct shader_func *main_func)
  559. {
  560. size_t i;
  561. dstr_cat(&glsp->gl_string, "\n\toutputval = _main_wrap(");
  562. for (i = 0; i < main_func->params.num; i++) {
  563. if (i)
  564. dstr_cat(&glsp->gl_string, ", ");
  565. dstr_cat(&glsp->gl_string, main_func->params.array[i].name);
  566. }
  567. dstr_cat(&glsp->gl_string, ");\n");
  568. }
  569. static void gl_write_main(struct gl_shader_parser *glsp, struct shader_func *main)
  570. {
  571. dstr_cat(&glsp->gl_string, "void main(void)\n{\n");
  572. gl_write_main_vars(glsp, main);
  573. gl_write_main_storage_inputs(glsp, main);
  574. gl_write_main_func_call(glsp, main);
  575. gl_write_main_storage_outputs(glsp, main);
  576. dstr_cat(&glsp->gl_string, "}\n");
  577. }
  578. /* ugh, don't ask. I'll probably get rid of the need for this function later */
  579. static void gl_rename_attributes(struct gl_shader_parser *glsp)
  580. {
  581. size_t i = 0, input_idx = 0, output_idx = 0;
  582. for (i = 0; i < glsp->attribs.num; i++) {
  583. struct gl_parser_attrib *attrib = glsp->attribs.array + i;
  584. struct dstr new_name = {0};
  585. const char *prefix;
  586. size_t val;
  587. if (attrib->input) {
  588. prefix = glsp->input_prefix;
  589. val = input_idx++;
  590. } else {
  591. prefix = glsp->output_prefix;
  592. val = output_idx++;
  593. }
  594. dstr_printf(&new_name, "%s%u", prefix, (unsigned int)val);
  595. dstr_replace(&glsp->gl_string, attrib->name.array, new_name.array);
  596. dstr_move(&attrib->name, &new_name);
  597. }
  598. }
  599. static bool gl_shader_buildstring(struct gl_shader_parser *glsp)
  600. {
  601. struct shader_func *main_func;
  602. main_func = shader_parser_getfunc(&glsp->parser, "main");
  603. if (!main_func) {
  604. blog(LOG_ERROR, "function 'main' not found");
  605. return false;
  606. }
  607. dstr_copy(&glsp->gl_string, "#version 330\n\n");
  608. dstr_cat(&glsp->gl_string, "const bool obs_glsl_compile = true;\n\n");
  609. dstr_cat(&glsp->gl_string, "vec4 obs_load_2d(sampler2D s, ivec3 p_lod)\n");
  610. dstr_cat(&glsp->gl_string, "{\n");
  611. dstr_cat(&glsp->gl_string, "\tint lod = p_lod.z;\n");
  612. dstr_cat(&glsp->gl_string, "\tvec2 size = textureSize(s, lod);\n");
  613. dstr_cat(&glsp->gl_string, "\tvec2 p = (vec2(p_lod.xy) + 0.5) / size;\n");
  614. dstr_cat(&glsp->gl_string, "\tvec4 color = textureLod(s, p, lod);\n");
  615. dstr_cat(&glsp->gl_string, "\treturn color;\n");
  616. dstr_cat(&glsp->gl_string, "}\n\n");
  617. dstr_cat(&glsp->gl_string, "vec4 obs_load_3d(sampler3D s, ivec4 p_lod)\n");
  618. dstr_cat(&glsp->gl_string, "{\n");
  619. dstr_cat(&glsp->gl_string, "\tint lod = p_lod.w;\n");
  620. dstr_cat(&glsp->gl_string, "\tvec3 size = textureSize(s, lod);\n");
  621. dstr_cat(&glsp->gl_string, "\tvec3 p = (vec3(p_lod.xyz) + 0.5) / size;\n");
  622. dstr_cat(&glsp->gl_string, "\tvec4 color = textureLod(s, p, lod);\n");
  623. dstr_cat(&glsp->gl_string, "\treturn color;\n");
  624. dstr_cat(&glsp->gl_string, "}\n\n");
  625. gl_write_params(glsp);
  626. gl_write_inputs(glsp, main_func);
  627. gl_write_outputs(glsp, main_func);
  628. gl_write_interface_block(glsp);
  629. gl_write_structs(glsp);
  630. gl_write_functions(glsp);
  631. gl_write_main(glsp, main_func);
  632. gl_rename_attributes(glsp);
  633. return true;
  634. }
  635. bool gl_shader_parse(struct gl_shader_parser *glsp, const char *shader_str, const char *file)
  636. {
  637. bool success = shader_parse(&glsp->parser, shader_str, file);
  638. char *str = shader_parser_geterrors(&glsp->parser);
  639. if (str) {
  640. blog(LOG_WARNING, "Shader parser errors/warnings:\n%s\n", str);
  641. bfree(str);
  642. }
  643. if (success)
  644. success = gl_shader_buildstring(glsp);
  645. return success;
  646. }