gl-shaderparser.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh 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 3 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_type_n(struct gl_shader_parser *glsp,
  17. const char *type, size_t len)
  18. {
  19. if (astrcmp_n(type, "float2", len) == 0)
  20. dstr_cat(&glsp->gl_string, "vec2");
  21. else if (astrcmp_n(type, "float3", len) == 0)
  22. dstr_cat(&glsp->gl_string, "vec3");
  23. else if (astrcmp_n(type, "float4", len) == 0)
  24. dstr_cat(&glsp->gl_string, "vec4");
  25. else if (astrcmp_n(type, "float3x3", len) == 0)
  26. dstr_cat(&glsp->gl_string, "mat3x3");
  27. else if (astrcmp_n(type, "float3x4", len) == 0)
  28. dstr_cat(&glsp->gl_string, "mat3x4");
  29. else if (astrcmp_n(type, "float4x4", len) == 0)
  30. dstr_cat(&glsp->gl_string, "mat4x4");
  31. else if (astrcmp_n(type, "texture2d", len) == 0)
  32. dstr_cat(&glsp->gl_string, "sampler2D");
  33. else if (astrcmp_n(type, "texture3d", len) == 0)
  34. dstr_cat(&glsp->gl_string, "sampler3D");
  35. else if (astrcmp_n(type, "texture_cube", len) == 0)
  36. dstr_cat(&glsp->gl_string, "samplerCube");
  37. else
  38. dstr_ncat(&glsp->gl_string, type, len);
  39. }
  40. static inline void gl_write_type(struct gl_shader_parser *glsp,
  41. const char *type)
  42. {
  43. gl_write_type_n(glsp, type, strlen(type));
  44. }
  45. static inline void gl_write_type_token(struct gl_shader_parser *glsp,
  46. struct cf_token *token)
  47. {
  48. gl_write_type_n(glsp, token->str.array, token->str.len);
  49. }
  50. static void gl_write_var(struct gl_shader_parser *glsp, struct shader_var *var)
  51. {
  52. if (var->var_type == SHADER_VAR_UNIFORM)
  53. dstr_cat(&glsp->gl_string, "uniform ");
  54. else if (var->var_type == SHADER_VAR_CONST)
  55. dstr_cat(&glsp->gl_string, "const ");
  56. gl_write_type(glsp, var->type);
  57. dstr_cat(&glsp->gl_string, " ");
  58. dstr_cat(&glsp->gl_string, var->name);
  59. dstr_cat(&glsp->gl_string, ";\n");
  60. }
  61. static inline void gl_write_params(struct gl_shader_parser *glsp)
  62. {
  63. size_t i;
  64. for (i = 0; i < glsp->parser.params.num; i++) {
  65. struct shader_var *var = glsp->parser.params.array+i;
  66. gl_write_var(glsp, var);
  67. }
  68. dstr_cat(&glsp->gl_string, "\n");
  69. }
  70. static void gl_write_storage_var(struct gl_shader_parser *glsp,
  71. struct shader_var *var, const char *storage,
  72. const char *prefix);
  73. /* unwraps a structure that's used for input/output */
  74. static void gl_unwrap_storage_struct(struct gl_shader_parser *glsp,
  75. struct shader_struct *st, const char *storage,
  76. const char *prefix)
  77. {
  78. struct dstr prefix_str;
  79. size_t i;
  80. dstr_init(&prefix_str);
  81. if (prefix)
  82. dstr_copy(&prefix_str, prefix);
  83. dstr_cat(&prefix_str, st->name);
  84. dstr_cat(&prefix_str, "_");
  85. for (i = 0; i < st->vars.num; i++) {
  86. struct shader_var *st_var = st->vars.array+i;
  87. gl_write_storage_var(glsp, st_var, storage, prefix_str.array);
  88. }
  89. dstr_free(&prefix_str);
  90. }
  91. static void gl_write_storage_var(struct gl_shader_parser *glsp,
  92. struct shader_var *var, const char *storage, const char *prefix)
  93. {
  94. struct shader_struct *st = shader_parser_getstruct(&glsp->parser,
  95. var->type);
  96. if (st) {
  97. gl_unwrap_storage_struct(glsp, st, storage, prefix);
  98. } else {
  99. if (storage) {
  100. dstr_cat(&glsp->gl_string, storage);
  101. dstr_cat(&glsp->gl_string, " ");
  102. }
  103. gl_write_type(glsp, var->type);
  104. dstr_cat(&glsp->gl_string, " ");
  105. if (prefix)
  106. dstr_cat(&glsp->gl_string, prefix);
  107. dstr_cat(&glsp->gl_string, var->name);
  108. dstr_cat(&glsp->gl_string, ";\n");
  109. }
  110. }
  111. static inline void gl_write_inputs(struct gl_shader_parser *glsp,
  112. struct shader_func *main)
  113. {
  114. size_t i;
  115. for (i = 0; i < main->params.num; i++) {
  116. struct shader_var *var = main->params.array+i;
  117. gl_write_storage_var(glsp, var, "in", "in_");
  118. }
  119. }
  120. static void gl_write_outputs(struct gl_shader_parser *glsp,
  121. struct shader_func *main)
  122. {
  123. struct shader_var var;
  124. shader_var_init(&var);
  125. var.type = bstrdup(main->return_type);
  126. var.name = bstrdup("return_val");
  127. if (main->return_mapping)
  128. var.mapping = bstrdup(main->return_mapping);
  129. gl_write_storage_var(glsp, &var, "out", "out_");
  130. shader_var_free(&var);
  131. }
  132. static void gl_write_struct(struct gl_shader_parser *glsp,
  133. struct shader_struct *st)
  134. {
  135. size_t i;
  136. dstr_cat(&glsp->gl_string, "struct ");
  137. dstr_cat(&glsp->gl_string, st->name);
  138. dstr_cat(&glsp->gl_string, " {\n");
  139. for (i = 0; i < st->vars.num; i++) {
  140. struct shader_var *var = st->vars.array+i;
  141. dstr_cat(&glsp->gl_string, "\t");
  142. gl_write_var(glsp, var);
  143. }
  144. dstr_cat(&glsp->gl_string, "};\n\n");
  145. }
  146. static inline void gl_write_structs(struct gl_shader_parser *glsp)
  147. {
  148. size_t i;
  149. for (i = 0; i < glsp->parser.structs.num; i++) {
  150. struct shader_struct *st = glsp->parser.structs.array+i;
  151. gl_write_struct(glsp, st);
  152. }
  153. }
  154. /*
  155. * NOTE: HLSL-> GLSL intrinsic conversions
  156. * atan2 -> atan
  157. * clip -> (unsupported)
  158. * ddx -> dFdx
  159. * ddy -> dFdy
  160. * fmod -> (unsupported)
  161. * frac -> fract
  162. * lerp -> mix
  163. * lit -> (unsupported)
  164. * log10 -> (unsupported)
  165. * mul -> (change to operator)
  166. * rsqrt -> inversesqrt
  167. * saturate -> (use clamp)
  168. * tex* -> texture
  169. * tex*grad -> textureGrad
  170. * tex*lod -> textureLod
  171. * tex*bias -> (use optional 'bias' value)
  172. * tex*proj -> textureProj
  173. *
  174. * All else can be left as-is
  175. */
  176. static void gl_write_functions(struct gl_shader_parser *glsp)
  177. {
  178. }
  179. static bool gl_shader_buildstring(struct gl_shader_parser *glsp)
  180. {
  181. struct shader_func *main = shader_parser_getfunc(&glsp->parser, "main");
  182. if (!main) {
  183. blog(LOG_ERROR, "function 'main' not found");
  184. return false;
  185. }
  186. dstr_copy(&glsp->gl_string, "#version 140\n\n");
  187. gl_write_params(glsp);
  188. gl_write_inputs(glsp, main);
  189. gl_write_outputs(glsp, main);
  190. gl_write_structs(glsp);
  191. gl_write_functions(glsp);
  192. // gl_write_main(glsp);
  193. return true;
  194. }
  195. bool gl_shader_parse(struct gl_shader_parser *glsp,
  196. const char *shader_str, const char *file)
  197. {
  198. bool success = shader_parse(&glsp->parser, shader_str, file);
  199. char *str = shader_parser_geterrors(&glsp->parser);
  200. if (str) {
  201. blog(LOG_WARNING, "Shader parser errors/warnings:\n%s\n", str);
  202. bfree(str);
  203. }
  204. return success;
  205. }