Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

před 8 roky
před 8 roky
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include <cstring>
  14. #include <cstdio>
  15. #if defined _WIN32
  16. # define WIN32_LEAN_AND_MEAN 1
  17. # include <windows.h>
  18. # undef WIN32_LEAN_AND_MEAN
  19. #endif
  20. #include "pegtl.hh"
  21. #include "lolgl.h"
  22. namespace lol
  23. {
  24. struct ShaderType
  25. {
  26. enum Value
  27. {
  28. Vertex = 1,
  29. Fragment,
  30. Geometry,
  31. TessControl,
  32. TessEval,
  33. }
  34. m_value;
  35. inline ShaderType(Value v) : m_value(v) {}
  36. inline ShaderType(int v) : m_value((Value)v) {}
  37. inline operator Value() { return m_value; }
  38. };
  39. static const char* attribute_names[] =
  40. {
  41. "in_Position",
  42. "in_BlendWeight",
  43. "in_BlendIndices",
  44. "in_Normal",
  45. "in_PointSize",
  46. "in_TexCoord",
  47. "in_TexCoordExt",
  48. "in_Tangent",
  49. "in_Binormal",
  50. "in_TessFactor",
  51. "in_PositionT",
  52. "in_Color",
  53. "in_Fog",
  54. "in_Depth",
  55. "in_Sample"
  56. };
  57. /*
  58. * Shader implementation class
  59. */
  60. class ShaderData
  61. {
  62. friend class Shader;
  63. private:
  64. String m_name;
  65. GLuint prog_id, vert_id, frag_id;
  66. // Benlitz: using a simple array could be faster since there is never more than a few attribute locations to store
  67. map<uint64_t, GLint> attrib_locations;
  68. map<uint64_t, bool> attrib_errors;
  69. uint32_t vert_crc, frag_crc;
  70. /* Shader patcher */
  71. static int GetVersion();
  72. static String Patch(String const &code, ShaderType type);
  73. /* Global shader cache */
  74. static Shader *shaders[];
  75. static hash<char const *> Hash;
  76. static int nshaders;
  77. };
  78. Shader *ShaderData::shaders[256];
  79. hash<char const *> ShaderData::Hash;
  80. int ShaderData::nshaders = 0;
  81. /*
  82. * LolFx parser
  83. */
  84. using namespace pegtl;
  85. struct lolfx_parser
  86. {
  87. public:
  88. String m_section;
  89. map<String, String> m_programs;
  90. private:
  91. // title <- '[' (!']')+ ']' .{eol}
  92. struct do_title
  93. : plus<not_one<']'>> {};
  94. struct title
  95. : seq<one<'['>,
  96. do_title,
  97. one<']'>,
  98. until<eol, any>> {};
  99. // FIXME: I’m using this rule because the do_title above also
  100. // gets triggered when using at<> which is non-consuming.
  101. struct title_ignore
  102. : seq<one<'['>,
  103. plus<not_one<']'>>,
  104. one<']'>,
  105. until<eol, any>> {};
  106. // code_line <- .{eol}
  107. struct code_line
  108. : until<eol, any> {};
  109. // code_section < code_line{&(title / eof)}
  110. struct code_section
  111. : until<at<sor<title_ignore, pegtl::eof>>, code_line> {};
  112. // shader < title code_section
  113. struct shader
  114. : seq<title, code_section> {};
  115. // header < code_section
  116. struct header
  117. : code_section {};
  118. // lolfx < header code_section*
  119. struct lolfx
  120. : seq<header, star<shader>> {};
  121. // default action: nothing
  122. template<typename RULE>
  123. struct action : nothing<RULE> {};
  124. public:
  125. lolfx_parser(String const &code)
  126. : m_section("header")
  127. {
  128. pegtl::parse_string<lolfx, action>(code.C(), "shader", this);
  129. }
  130. };
  131. template<>
  132. struct lolfx_parser::action<lolfx_parser::do_title>
  133. {
  134. static void apply(action_input const &in, lolfx_parser *that)
  135. {
  136. that->m_section = in.string().c_str();
  137. }
  138. };
  139. template<>
  140. struct lolfx_parser::action<lolfx_parser::code_section>
  141. {
  142. static void apply(action_input const &in, lolfx_parser *that)
  143. {
  144. that->m_programs[that->m_section] = in.string().c_str();
  145. }
  146. };
  147. /*
  148. * Public Shader class
  149. */
  150. Shader *Shader::Create(String const &name, String const &code)
  151. {
  152. lolfx_parser p(code);
  153. ASSERT(p.m_programs.has_key("vert.glsl"),
  154. "no vertex shader in %s", name.C());
  155. ASSERT(p.m_programs.has_key("frag.glsl"),
  156. "no fragment shader in %s", name.C());
  157. String vert = p.m_programs["vert.glsl"];
  158. String frag = p.m_programs["frag.glsl"];
  159. uint32_t new_vert_crc = ShaderData::Hash(vert);
  160. uint32_t new_frag_crc = ShaderData::Hash(frag);
  161. for (int n = 0; n < ShaderData::nshaders; n++)
  162. {
  163. if (ShaderData::shaders[n]->data->vert_crc == new_vert_crc
  164. && ShaderData::shaders[n]->data->frag_crc == new_frag_crc)
  165. {
  166. return ShaderData::shaders[n];
  167. }
  168. }
  169. Shader *ret = new Shader(name, vert, frag);
  170. ShaderData::shaders[ShaderData::nshaders] = ret;
  171. ShaderData::nshaders++;
  172. return ret;
  173. }
  174. void Shader::Destroy(Shader *shader)
  175. {
  176. /* XXX: do nothing! the shader should remain in cache */
  177. UNUSED(shader);
  178. }
  179. Shader::Shader(String const &name,
  180. String const &vert, String const &frag)
  181. : data(new ShaderData())
  182. {
  183. data->m_name = name;
  184. char errbuf[4096];
  185. String shader_code;
  186. GLchar const *gl_code;
  187. GLint status;
  188. GLsizei len;
  189. /* Compile vertex shader */
  190. data->vert_crc = ShaderData::Hash(vert);
  191. shader_code = ShaderData::Patch(vert, ShaderType::Vertex);
  192. data->vert_id = glCreateShader(GL_VERTEX_SHADER);
  193. gl_code = shader_code.C();
  194. glShaderSource(data->vert_id, 1, &gl_code, nullptr);
  195. glCompileShader(data->vert_id);
  196. glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf);
  197. glGetShaderiv(data->vert_id, GL_COMPILE_STATUS, &status);
  198. if (status != GL_TRUE)
  199. {
  200. msg::error("failed to compile vertex shader %s: %s\n",
  201. name.C(), errbuf);
  202. msg::error("shader source:\n%s\n", shader_code.C());
  203. }
  204. else if (len > 16)
  205. {
  206. msg::debug("compile log for vertex shader %s: %s\n", name.C(), errbuf);
  207. msg::debug("shader source:\n%s\n", shader_code.C());
  208. }
  209. /* Compile fragment shader */
  210. data->frag_crc = ShaderData::Hash(frag);
  211. shader_code = ShaderData::Patch(frag, ShaderType::Fragment);
  212. data->frag_id = glCreateShader(GL_FRAGMENT_SHADER);
  213. gl_code = shader_code.C();
  214. glShaderSource(data->frag_id, 1, &gl_code, nullptr);
  215. glCompileShader(data->frag_id);
  216. glGetShaderInfoLog(data->frag_id, sizeof(errbuf), &len, errbuf);
  217. glGetShaderiv(data->frag_id, GL_COMPILE_STATUS, &status);
  218. if (status != GL_TRUE)
  219. {
  220. msg::error("failed to compile fragment shader %s: %s\n",
  221. name.C(), errbuf);
  222. msg::error("shader source:\n%s\n", shader_code.C());
  223. }
  224. else if (len > 16)
  225. {
  226. msg::debug("compile log for fragment shader %s: %s\n",
  227. name.C(), errbuf);
  228. msg::debug("shader source:\n%s\n", shader_code.C());
  229. }
  230. /* Create program */
  231. data->prog_id = glCreateProgram();
  232. glAttachShader(data->prog_id, data->vert_id);
  233. glAttachShader(data->prog_id, data->frag_id);
  234. glLinkProgram(data->prog_id);
  235. glGetProgramInfoLog(data->prog_id, sizeof(errbuf), &len, errbuf);
  236. glGetProgramiv(data->prog_id, GL_LINK_STATUS, &status);
  237. if (status != GL_TRUE)
  238. {
  239. msg::error("failed to link program %s: %s\n", name.C(), errbuf);
  240. }
  241. else if (len > 16)
  242. {
  243. msg::debug("link log for program %s: %s\n", name.C(), errbuf);
  244. }
  245. GLint validated;
  246. glValidateProgram(data->prog_id);
  247. glGetProgramiv(data->prog_id, GL_VALIDATE_STATUS, &validated);
  248. if (validated != GL_TRUE)
  249. {
  250. msg::error("failed to validate program %s\n", name.C());
  251. }
  252. GLint num_attribs;
  253. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTES, &num_attribs);
  254. #if EMSCRIPTEN //WebGL doesn't support GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, so chose a default size value.
  255. GLint max_len = 256;
  256. #else
  257. GLint max_len;
  258. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
  259. #endif
  260. char* name_buffer = new char[max_len];
  261. for (int i = 0; i < num_attribs; ++i)
  262. {
  263. int attrib_len;
  264. int attrib_size;
  265. int attrib_type;
  266. glGetActiveAttrib(data->prog_id, i, max_len, &attrib_len, (GLint*)&attrib_size, (GLenum*)&attrib_type, name_buffer);
  267. String name(name_buffer);
  268. int index = -1;
  269. VertexUsage usage = VertexUsage::MAX;
  270. for (int j = 0; j < (int)VertexUsage::MAX; ++j)
  271. {
  272. if (name.starts_with(attribute_names[j]) ||
  273. name.starts_with(String(attribute_names[j]).to_lower()))
  274. {
  275. usage = VertexUsage(j);
  276. char* idx_ptr = name.C() + strlen(attribute_names[j]);
  277. index = strtol(idx_ptr, nullptr, 10);
  278. break;
  279. }
  280. }
  281. if (usage == VertexUsage::MAX || index == -1)
  282. {
  283. msg::error("unable to parse attribute semantic from name: %s\n",
  284. name_buffer);
  285. }
  286. else
  287. {
  288. GLint location = glGetAttribLocation(data->prog_id, name_buffer);
  289. uint64_t flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  290. flags |= (uint64_t)(uint16_t)index;
  291. // TODO: this is here just in case. Remove this once everything has been correctly tested
  292. #if _DEBUG
  293. if (data->attrib_locations.has_key(flags))
  294. {
  295. msg::error("error while parsing attribute semantics in %s\n",
  296. name.C());
  297. }
  298. #endif
  299. data->attrib_locations[flags] = location;
  300. }
  301. }
  302. delete[] name_buffer;
  303. }
  304. int Shader::GetAttribCount() const
  305. {
  306. return data->attrib_locations.count();
  307. }
  308. ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const
  309. {
  310. ShaderAttrib ret;
  311. ret.m_flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  312. ret.m_flags |= (uint64_t)(uint16_t)index;
  313. GLint l = -1;
  314. if (!data->attrib_locations.try_get(ret.m_flags, l))
  315. {
  316. /* Only spit an error once, we don’t need to flood the console. */
  317. if (!data->attrib_errors.has_key(ret.m_flags))
  318. {
  319. msg::error("attribute %s not found in shader %s\n",
  320. usage.ToString().C(), data->m_name.C());
  321. data->attrib_errors[ret.m_flags] = true;
  322. }
  323. }
  324. ret.m_flags |= (uint64_t)(uint32_t)l << 32;
  325. return ret;
  326. }
  327. ShaderUniform Shader::GetUniformLocation(String const& uni) const
  328. {
  329. return GetUniformLocation(uni.C());
  330. }
  331. ShaderUniform Shader::GetUniformLocation(char const *uni) const
  332. {
  333. ShaderUniform ret;
  334. ret.frag = (uintptr_t)glGetUniformLocation(data->prog_id, uni);
  335. ret.vert = 0;
  336. return ret;
  337. }
  338. /*
  339. * Uniform setters for scalars
  340. */
  341. void Shader::SetUniform(ShaderUniform const &uni, int i)
  342. {
  343. glUniform1i((GLint)uni.frag, i);
  344. }
  345. void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v)
  346. {
  347. glUniform2i((GLint)uni.frag, v.x, v.y);
  348. }
  349. void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v)
  350. {
  351. glUniform3i((GLint)uni.frag, v.x, v.y, v.z);
  352. }
  353. void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v)
  354. {
  355. glUniform4i((GLint)uni.frag, v.x, v.y, v.z, v.w);
  356. }
  357. void Shader::SetUniform(ShaderUniform const &uni, float f)
  358. {
  359. glUniform1f((GLint)uni.frag, f);
  360. }
  361. void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v)
  362. {
  363. glUniform2fv((GLint)uni.frag, 1, &v[0]);
  364. }
  365. void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v)
  366. {
  367. glUniform3fv((GLint)uni.frag, 1, &v[0]);
  368. }
  369. void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v)
  370. {
  371. glUniform4fv((GLint)uni.frag, 1, &v[0]);
  372. }
  373. void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m)
  374. {
  375. glUniformMatrix2fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  376. }
  377. void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m)
  378. {
  379. glUniformMatrix3fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  380. }
  381. void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
  382. {
  383. glUniformMatrix4fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  384. }
  385. void Shader::SetUniform(ShaderUniform const &uni, TextureUniform tex, int index)
  386. {
  387. glActiveTexture(GL_TEXTURE0 + index);
  388. //glEnable(GL_TEXTURE_2D);
  389. glBindTexture(GL_TEXTURE_2D, (int)tex.m_flags);
  390. SetUniform(uni, index);
  391. }
  392. /*
  393. * Uniform setters for arrays
  394. */
  395. void Shader::SetUniform(ShaderUniform const &uni, array<float> const &v)
  396. {
  397. glUniform1fv((GLint)uni.frag, (GLsizei)v.count(), &v[0]);
  398. }
  399. void Shader::SetUniform(ShaderUniform const &uni, array<vec2> const &v)
  400. {
  401. glUniform2fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  402. }
  403. void Shader::SetUniform(ShaderUniform const &uni, array<vec3> const &v)
  404. {
  405. glUniform3fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  406. }
  407. void Shader::SetUniform(ShaderUniform const &uni, array<vec4> const &v)
  408. {
  409. glUniform4fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  410. }
  411. void Shader::Bind() const
  412. {
  413. glUseProgram(data->prog_id);
  414. }
  415. void Shader::Unbind() const
  416. {
  417. /* FIXME: untested */
  418. glUseProgram(0);
  419. }
  420. Shader::~Shader()
  421. {
  422. glDetachShader(data->prog_id, data->vert_id);
  423. glDetachShader(data->prog_id, data->frag_id);
  424. glDeleteShader(data->vert_id);
  425. glDeleteShader(data->frag_id);
  426. glDeleteProgram(data->prog_id);
  427. delete data;
  428. }
  429. /* Try to detect shader compiler features */
  430. int ShaderData::GetVersion()
  431. {
  432. static int version = 0;
  433. if (!version)
  434. {
  435. #if defined HAVE_GLES_2X
  436. /* GLES 2.x supports #version 100, that's all. */
  437. return 100;
  438. #else
  439. char buf[4096];
  440. GLsizei len;
  441. int id = glCreateShader(GL_VERTEX_SHADER);
  442. /* Can we compile 1.30 shaders? */
  443. char const *test130 =
  444. "#version 130\n"
  445. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  446. glShaderSource(id, 1, &test130, nullptr);
  447. glCompileShader(id);
  448. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  449. if (len <= 0)
  450. version = 130;
  451. /* If not, can we compile 1.20 shaders? */
  452. if (!version)
  453. {
  454. char const *test120 =
  455. "#version 120\n"
  456. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  457. glShaderSource(id, 1, &test120, nullptr);
  458. glCompileShader(id);
  459. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  460. if (len <= 0)
  461. version = 120;
  462. }
  463. /* Otherwise, assume we can compile 1.10 shaders. */
  464. if (!version)
  465. version = 110;
  466. glDeleteShader(id);
  467. #endif
  468. }
  469. return version;
  470. }
  471. /*
  472. * Simple shader source patching for old GLSL versions.
  473. */
  474. String ShaderData::Patch(String const &code, ShaderType type)
  475. {
  476. int ver_driver = GetVersion();
  477. String patched_code = code;
  478. if (ver_driver >= 130)
  479. return patched_code;
  480. int ver_shader = 110;
  481. char *parser = strstr(patched_code.C(), "#version");
  482. if (parser)
  483. ver_shader = atoi(parser + strlen("#version"));
  484. /* This is GL ES, we only know version 100. */
  485. if (ver_shader > 100 && ver_driver == 100)
  486. {
  487. /* FIXME: this isn't elegant but honestly, we don't care, this
  488. * whole file is going to die soon. */
  489. char *p = strstr(patched_code.C(), "#version");
  490. if (p)
  491. {
  492. p += 8;
  493. while (*p == ' ')
  494. p++;
  495. if (p[0] == '1' && p[1] && p[2])
  496. p[1] = p[2] = '0';
  497. }
  498. }
  499. if (ver_shader > 120 && ver_driver <= 120)
  500. {
  501. char const *end = patched_code.C() + patched_code.count() + 1;
  502. /* Find main() */
  503. parser = strstr(patched_code.C(), "main");
  504. if (!parser) return patched_code;
  505. parser = strstr(parser, "(");
  506. if (!parser) return patched_code;
  507. parser = strstr(parser, ")");
  508. if (!parser) return patched_code;
  509. parser = strstr(parser, "{");
  510. if (!parser) return patched_code;
  511. char *main = parser + 1;
  512. /* Perform main() replaces */
  513. char const * const main_replaces[] =
  514. {
  515. #if 0
  516. "in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;",
  517. "in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;",
  518. "in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;",
  519. "in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;",
  520. "in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;",
  521. "in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;",
  522. "in vec2 in_MultiTexCoord0;",
  523. "vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;",
  524. "in vec2 in_MultiTexCoord1;",
  525. "vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;",
  526. "in vec2 in_MultiTexCoord2;",
  527. "vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;",
  528. "in vec2 in_MultiTexCoord3;",
  529. "vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;",
  530. "in vec2 in_MultiTexCoord4;",
  531. "vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;",
  532. "in vec2 in_MultiTexCoord5;",
  533. "vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;",
  534. "in vec2 in_MultiTexCoord6;",
  535. "vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;",
  536. "in vec2 in_MultiTexCoord7;",
  537. "vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;",
  538. #endif
  539. nullptr
  540. };
  541. for (char const * const *rep = main_replaces; rep[0]; rep += 2)
  542. {
  543. char *match = strstr(patched_code.C(), rep[0]);
  544. if (match && match < main)
  545. {
  546. size_t l0 = strlen(rep[0]);
  547. size_t l1 = strlen(rep[1]);
  548. memmove(main + l1, main, end - main);
  549. memcpy(main, rep[1], l1);
  550. memset(match, ' ', l0);
  551. main += l1;
  552. end += l1;
  553. }
  554. }
  555. /* Perform small replaces */
  556. char const * const fast_replaces[] =
  557. {
  558. "#version 130", "#version 120",
  559. "out vec4 out_color;", " ",
  560. "out_color =", "gl_FragColor =",
  561. "in vec2", type == ShaderType::Vertex ? "attribute vec2" : "varying vec2",
  562. "in vec3", type == ShaderType::Vertex ? "attribute vec3" : "varying vec3",
  563. "in vec4", type == ShaderType::Vertex ? "attribute vec4" : "varying vec4",
  564. "in mat4", type == ShaderType::Vertex ? "attribute mat4" : "varying mat4",
  565. "out vec2", "varying vec2",
  566. "out vec3", "varying vec3",
  567. "out vec4", "varying vec4",
  568. "out mat4", "varying mat4",
  569. nullptr
  570. };
  571. for (char const * const *rep = fast_replaces; rep[0]; rep += 2)
  572. {
  573. while (true)
  574. {
  575. int index = patched_code.index_of(rep[0]);
  576. if (index == INDEX_NONE)
  577. break;
  578. size_t l0 = strlen(rep[0]);
  579. size_t l1 = strlen(rep[1]);
  580. String left = patched_code.sub(0, index);
  581. String right = patched_code.sub(index + l0, patched_code.count() - (index + l0));
  582. patched_code = left + String(rep[1]) + right;
  583. }
  584. }
  585. }
  586. return patched_code;
  587. }
  588. static const String g_ret = "\n";
  589. static const String g_eol = ";";
  590. static const String g_bop = "{";
  591. static const String g_bcl = "}";
  592. static const String g_tab = " ";
  593. //----
  594. String Shader::GetVariablePrefix(const ShaderVariable variable)
  595. {
  596. switch (variable.ToScalar())
  597. {
  598. case ShaderVariable::Attribute: return String("in_");
  599. case ShaderVariable::Uniform: return String("u_");
  600. case ShaderVariable::Varying: return String("pass_");
  601. case ShaderVariable::InOut:
  602. default: return String();
  603. }
  604. }
  605. //----
  606. String Shader::GetVariableQualifier(const ShaderVariable variable)
  607. {
  608. switch (variable.ToScalar())
  609. {
  610. case ShaderVariable::Attribute: return String("attribute");
  611. case ShaderVariable::Uniform: return String("uniform");
  612. case ShaderVariable::Varying: return String("varying");
  613. case ShaderVariable::InOut:
  614. default: return String();
  615. }
  616. }
  617. //----
  618. String Shader::GetFunctionQualifier(const ShaderVariable variable, const ShaderProgram program)
  619. {
  620. switch (program.ToScalar())
  621. {
  622. case ShaderProgram::Geometry:
  623. {
  624. //TODO : L O L ----------------
  625. return String();
  626. }
  627. case ShaderProgram::Vertex:
  628. {
  629. switch (variable.ToScalar())
  630. {
  631. case ShaderVariable::Attribute: return String("in");
  632. case ShaderVariable::Uniform: return String("in");
  633. case ShaderVariable::Varying: return String("inout");
  634. case ShaderVariable::InOut: return String("inout");
  635. default: return String();
  636. }
  637. return String();
  638. }
  639. case ShaderProgram::Pixel:
  640. {
  641. switch (variable.ToScalar())
  642. {
  643. case ShaderVariable::Attribute: return String("in");
  644. case ShaderVariable::Uniform: return String("in");
  645. case ShaderVariable::Varying: return String("in");
  646. case ShaderVariable::InOut: return String("inout");
  647. default: return String();
  648. }
  649. return String();
  650. }
  651. default:
  652. {
  653. return String();
  654. }
  655. }
  656. }
  657. //----
  658. String Shader::GetProgramQualifier(const ShaderProgram program)
  659. {
  660. switch (program.ToScalar())
  661. {
  662. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  663. case ShaderProgram::Vertex: return String("[vert.glsl]");
  664. case ShaderProgram::Pixel: return String("[frag.glsl]");
  665. default: return String();
  666. }
  667. }
  668. //----
  669. String Shader::GetProgramOutVariable(const ShaderProgram program)
  670. {
  671. switch (program.ToScalar())
  672. {
  673. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  674. case ShaderProgram::Vertex: return String("gl_Position");
  675. case ShaderProgram::Pixel: return String("gl_FragColor");
  676. default: return String();
  677. }
  678. }
  679. //----
  680. String Shader::GetProgramOutVariableLocal(const ShaderProgram program)
  681. {
  682. switch (program.ToScalar())
  683. {
  684. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  685. case ShaderProgram::Vertex: return String("out_position");
  686. case ShaderProgram::Pixel: return String("out_frag_color");
  687. default: return String();
  688. }
  689. }
  690. //ShaderVar -------------------------------------------------------------------
  691. ShaderVar ShaderVar::GetShaderOut(ShaderProgram program)
  692. {
  693. switch (program.ToScalar())
  694. {
  695. case ShaderProgram::Geometry: //TODO : L O L ------------------------------
  696. default: ASSERT(false); return ShaderVar();
  697. case ShaderProgram::Vertex: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program));
  698. case ShaderProgram::Pixel: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program));
  699. }
  700. }
  701. //Shader Block implementation class -------------------------------------------
  702. void ShaderBlock::AddVar(ShaderVar const& var)
  703. {
  704. ShaderVariable qualifier = var.GetQualifier();
  705. String type = var.GetType();
  706. String name = Shader::GetVariablePrefix(qualifier) + var.m_name;
  707. ASSERT(!m_parameters[qualifier.ToScalar()].has_key(name));
  708. m_parameters[qualifier.ToScalar()][name] = type;
  709. }
  710. //----
  711. void ShaderBlock::AddCallParameters(map<String, String> const& variables, String& result)
  712. {
  713. array<String> keys = variables.keys();
  714. for (String key : keys)
  715. {
  716. if (result.count() > 0)
  717. result += ", ";
  718. result += key;
  719. }
  720. }
  721. //----
  722. void ShaderBlock::AddDefinitionParameters(const ShaderVariable type, const ShaderProgram program, map<String, String>& variables, String& result)
  723. {
  724. array<String> keys = variables.keys();
  725. for (String key : keys)
  726. {
  727. if (result.count() > 0)
  728. result += ", ";
  729. result += Shader::GetFunctionQualifier(type, program) + " ";
  730. result += variables[key];
  731. result += String(" ");
  732. result += key;
  733. }
  734. }
  735. //----
  736. void ShaderBlock::Build(const ShaderProgram program, String& call, String& function)
  737. {
  738. ASSERT(m_name.count());
  739. ASSERT(m_parameters[ShaderVariable::InOut].count());
  740. //Build call in main
  741. String call_name = String("Call_") + m_name;
  742. call = call_name + "(";
  743. String call_parameters;
  744. for (int i = 0; i < ShaderVariable::MAX; i++)
  745. AddCallParameters(/*(ShaderVariable)i, */m_parameters[i], call_parameters);
  746. call += call_parameters + ");";
  747. //Build function declaration
  748. function = String("void ") + call_name + "(";
  749. String def_parameters;
  750. for (int i = 0; i < ShaderVariable::MAX; i++)
  751. AddDefinitionParameters((ShaderVariable)i, program, m_parameters[i], def_parameters);
  752. function += def_parameters + ")" + g_ret +
  753. "{" + g_ret +
  754. m_code_main + ((m_code_main.ends_with(g_ret)) ? (String()) : (g_ret)) +
  755. "}";
  756. }
  757. //Shader Builder implementation class -----------------------------------------
  758. ShaderBuilder::ShaderBuilder(String const& name, String const& version)
  759. : m_name(name), m_version(version)
  760. {
  761. ASSERT(name.count());
  762. ASSERT(version.count());
  763. }
  764. //----
  765. ShaderBuilder::~ShaderBuilder()
  766. {
  767. }
  768. //----
  769. String const& ShaderBuilder::GetName()
  770. {
  771. return m_name;
  772. }
  773. //----
  774. ShaderBuilder& ShaderBuilder::operator<<(const ShaderProgram program)
  775. {
  776. m_current_program = program;
  777. return *this;
  778. }
  779. //----
  780. ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock* block)
  781. {
  782. ASSERT(m_current_program != ShaderProgram::MAX);
  783. m_blocks[m_current_program.ToScalar()].push_unique(block);
  784. return *this;
  785. }
  786. //----
  787. ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock const& block)
  788. {
  789. ASSERT(m_current_program != ShaderProgram::MAX);
  790. m_blocks[m_current_program.ToScalar()].push_unique(new ShaderBlock(block));
  791. return *this;
  792. }
  793. //----
  794. String ShaderBuilder::AddSlotOutVariableLocal(const ShaderProgram program)
  795. {
  796. ShaderVariable var = ShaderVariable::InOut;
  797. String result = Shader::GetProgramOutVariableLocal(program);
  798. switch (program.ToScalar())
  799. {
  800. case ShaderProgram::Geometry:
  801. {
  802. //TODO : L O L ----------------
  803. break;
  804. }
  805. case ShaderProgram::Vertex:
  806. {
  807. m_parameters[program.ToScalar()][var.ToScalar()][result] = "vec4";
  808. break;
  809. }
  810. case ShaderProgram::Pixel:
  811. {
  812. m_parameters[program.ToScalar()][var.ToScalar()][result] = "vec4";
  813. break;
  814. }
  815. default:
  816. {
  817. break;
  818. }
  819. }
  820. return result;
  821. }
  822. //----
  823. void ShaderBuilder::MergeParameters(map<String, String>& variables, map<String, String>& merged)
  824. {
  825. array<String> keys = variables.keys();
  826. for (String key : keys)
  827. {
  828. bool has_key = merged.has_key(key);
  829. //Key exists, check the type to make sure it's the same
  830. ASSERT(!has_key || (has_key && merged[key] == variables[key]),
  831. "has_key=%d, key=%s merged[key]=%s, variables[key]=%s\n",
  832. (int)has_key, key.C(), merged[key].C(), variables[key].C());
  833. //does not exist, had it
  834. if (!has_key)
  835. merged[key] = variables[key];
  836. }
  837. }
  838. //----
  839. void ShaderBuilder::Build(String& code)
  840. {
  841. //Cleanup first
  842. for (int prog = 0; prog < ShaderProgram::MAX; prog++)
  843. for (int var = 0; var < ShaderVariable::MAX; var++)
  844. m_parameters[prog][var].empty();
  845. //Start building
  846. for (int prog = 0; prog < ShaderProgram::MAX; prog++)
  847. {
  848. //Add default local out in merged variables
  849. String out_local_var = AddSlotOutVariableLocal((ShaderProgram)prog);
  850. if (!out_local_var.count())
  851. continue;
  852. //Merge all variables
  853. for (int var = 0; var < ShaderVariable::MAX; var++)
  854. for (int block = 0; block < m_blocks[prog].count(); block++)
  855. MergeParameters(m_blocks[prog][block]->m_parameters[var], m_parameters[prog][var]);
  856. //Actually write code
  857. code += Shader::GetProgramQualifier((ShaderProgram)prog) + g_ret;
  858. //Add actual code
  859. code += String("#version ") + m_version + g_ret + g_ret;
  860. //Added shader variables
  861. for (int var = 0; var < ShaderVariable::InOut; var++)
  862. {
  863. array<String> keys = m_parameters[prog][var].keys();
  864. if (keys.count())
  865. {
  866. code += String("//- ") + Shader::GetVariableQualifier((ShaderVariable)var) + " ----" + g_ret;
  867. for (String key : keys)
  868. {
  869. code += Shader::GetVariableQualifier((ShaderVariable)var) + " ";
  870. code += m_parameters[prog][var][key] + " " + key + ";" + g_ret;
  871. }
  872. if (var + 1 < ShaderVariable::InOut)
  873. code += g_ret;
  874. }
  875. }
  876. code += g_ret;
  877. //Build Blocks code and add it
  878. array<String> calls;
  879. for (int block = 0; block < m_blocks[prog].count(); block++)
  880. {
  881. String call;
  882. String function;
  883. m_blocks[prog][block]->Build(ShaderProgram(prog), call, function);
  884. calls << call;
  885. if (m_blocks[prog][block]->m_code_custom.count())
  886. {
  887. code += String("//- ") + m_blocks[prog][block]->GetName() + " custom code ----" + g_ret;
  888. code += m_blocks[prog][block]->m_code_custom + g_ret + g_ret;
  889. }
  890. code += String("//- ") + m_blocks[prog][block]->GetName() + " main code ----" + g_ret;
  891. code += function + g_ret + g_ret;
  892. }
  893. //Added main definition
  894. code += String("//- Main ----") + g_ret +
  895. String("void main(void)") + g_ret + "{" + g_ret;
  896. //Add local variables
  897. int var = ShaderVariable::InOut;
  898. array<String> keys = m_parameters[prog][var].keys();
  899. for (String key : keys)
  900. {
  901. if (keys.count())
  902. {
  903. code += g_tab + m_parameters[prog][var][key] + " " + key + ";" + g_ret;
  904. }
  905. }
  906. code += g_ret;
  907. //Add calls
  908. code += g_tab + String("//- Calls ----") + g_ret;
  909. for (String call : calls)
  910. code += g_tab + call + g_ret;
  911. code += g_ret;
  912. code += g_tab + Shader::GetProgramOutVariable((ShaderProgram)prog) + " = " + out_local_var + ";" + g_ret +
  913. String("}") + g_ret + g_ret;
  914. }
  915. }
  916. } /* namespace lol */