Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

1300 wiersze
38 KiB

  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. # if defined USE_D3D9
  20. # include <algorithm>
  21. using std::min;
  22. using std::max;
  23. # include <d3d9.h>
  24. # include <d3dx9shader.h>
  25. # endif
  26. #endif
  27. #include "pegtl.hh"
  28. #include "lolgl.h"
  29. namespace lol
  30. {
  31. struct ShaderType
  32. {
  33. enum Value
  34. {
  35. Vertex = 1,
  36. Fragment,
  37. Geometry,
  38. TessControl,
  39. TessEval,
  40. }
  41. m_value;
  42. inline ShaderType(Value v) : m_value(v) {}
  43. inline ShaderType(int v) : m_value((Value)v) {}
  44. inline operator Value() { return m_value; }
  45. };
  46. static const char* attribute_names[] =
  47. {
  48. "in_Position",
  49. "in_BlendWeight",
  50. "in_BlendIndices",
  51. "in_Normal",
  52. "in_PointSize",
  53. "in_TexCoord",
  54. "in_TexCoordExt",
  55. "in_Tangent",
  56. "in_Binormal",
  57. "in_TessFactor",
  58. "in_PositionT",
  59. "in_Color",
  60. "in_Fog",
  61. "in_Depth",
  62. "in_Sample"
  63. };
  64. /*
  65. * Shader implementation class
  66. */
  67. class ShaderData
  68. {
  69. friend class Shader;
  70. private:
  71. String m_name;
  72. #if defined USE_D3D9
  73. IDirect3DDevice9 *m_dev;
  74. IDirect3DVertexShader9 *vert_shader;
  75. IDirect3DPixelShader9 *frag_shader;
  76. ID3DXConstantTable *vert_table, *frag_table;
  77. #else
  78. GLuint prog_id, vert_id, frag_id;
  79. // Benlitz: using a simple array could be faster since there is never more than a few attribute locations to store
  80. map<uint64_t, GLint> attrib_locations;
  81. map<uint64_t, bool> attrib_errors;
  82. #endif
  83. uint32_t vert_crc, frag_crc;
  84. /* Shader patcher */
  85. static int GetVersion();
  86. static String Patch(String const &code, ShaderType type);
  87. /* Global shader cache */
  88. static Shader *shaders[];
  89. static hash<char const *> Hash;
  90. static int nshaders;
  91. };
  92. Shader *ShaderData::shaders[256];
  93. hash<char const *> ShaderData::Hash;
  94. int ShaderData::nshaders = 0;
  95. /*
  96. * LolFx parser
  97. */
  98. using namespace pegtl;
  99. struct lolfx_parser
  100. {
  101. public:
  102. String m_section;
  103. map<String, String> m_programs;
  104. private:
  105. // title <- '[' (!']')+ ']' .{eol}
  106. struct do_title
  107. : plus<not_one<']'>> {};
  108. struct title
  109. : seq<one<'['>,
  110. do_title,
  111. one<']'>,
  112. until<eol, any>> {};
  113. // FIXME: I’m using this rule because the do_title above also
  114. // gets triggered when using at<> which is non-consuming.
  115. struct title_ignore
  116. : seq<one<'['>,
  117. plus<not_one<']'>>,
  118. one<']'>,
  119. until<eol, any>> {};
  120. // code_line <- .{eol}
  121. struct code_line
  122. : until<eol, any> {};
  123. // code_section < code_line{&(title / eof)}
  124. struct code_section
  125. : until<at<sor<title_ignore, pegtl::eof>>, code_line> {};
  126. // shader < title code_section
  127. struct shader
  128. : seq<title, code_section> {};
  129. // header < code_section
  130. struct header
  131. : code_section {};
  132. // lolfx < header code_section*
  133. struct lolfx
  134. : seq<header, star<shader>> {};
  135. // default action: nothing
  136. template<typename RULE>
  137. struct action : nothing<RULE> {};
  138. public:
  139. lolfx_parser(String const &code)
  140. : m_section("header")
  141. {
  142. pegtl::parse_string<lolfx, action>(code.C(), "shader", this);
  143. }
  144. };
  145. template<>
  146. struct lolfx_parser::action<lolfx_parser::do_title>
  147. {
  148. static void apply(action_input const &in, lolfx_parser *that)
  149. {
  150. that->m_section = in.string().c_str();
  151. }
  152. };
  153. template<>
  154. struct lolfx_parser::action<lolfx_parser::code_section>
  155. {
  156. static void apply(action_input const &in, lolfx_parser *that)
  157. {
  158. that->m_programs[that->m_section] = in.string().c_str();
  159. }
  160. };
  161. /*
  162. * Public Shader class
  163. */
  164. Shader *Shader::Create(String const &name, String const &code)
  165. {
  166. lolfx_parser p(code);
  167. ASSERT(p.m_programs.has_key("vert.glsl"),
  168. "no vertex shader in %s", name.C());
  169. ASSERT(p.m_programs.has_key("frag.glsl"),
  170. "no fragment shader in %s", name.C());
  171. String vert = p.m_programs["vert.glsl"];
  172. String frag = p.m_programs["frag.glsl"];
  173. uint32_t new_vert_crc = ShaderData::Hash(vert);
  174. uint32_t new_frag_crc = ShaderData::Hash(frag);
  175. for (int n = 0; n < ShaderData::nshaders; n++)
  176. {
  177. if (ShaderData::shaders[n]->data->vert_crc == new_vert_crc
  178. && ShaderData::shaders[n]->data->frag_crc == new_frag_crc)
  179. {
  180. return ShaderData::shaders[n];
  181. }
  182. }
  183. Shader *ret = new Shader(name, vert, frag);
  184. ShaderData::shaders[ShaderData::nshaders] = ret;
  185. ShaderData::nshaders++;
  186. return ret;
  187. }
  188. void Shader::Destroy(Shader *shader)
  189. {
  190. /* XXX: do nothing! the shader should remain in cache */
  191. UNUSED(shader);
  192. }
  193. Shader::Shader(String const &name,
  194. String const &vert, String const &frag)
  195. : data(new ShaderData())
  196. {
  197. data->m_name = name;
  198. #if defined USE_D3D9
  199. ID3DXBuffer *shader_code, *error_msg;
  200. HRESULT hr;
  201. D3DXMACRO macros[] =
  202. {
  203. { "LOL_TEST_MACRO", "1" },
  204. { nullptr, nullptr }
  205. };
  206. #else
  207. char errbuf[4096];
  208. String shader_code;
  209. GLchar const *gl_code;
  210. GLint status;
  211. GLsizei len;
  212. #endif
  213. /* Compile vertex shader */
  214. data->vert_crc = ShaderData::Hash(vert);
  215. #if defined USE_D3D9
  216. data->m_dev = (IDirect3DDevice9 *)Renderer::Get()->GetDevice();
  217. hr = D3DXCompileShader(vert, (UINT)strlen(vert), macros, nullptr, "main",
  218. "vs_3_0", 0, &shader_code, &error_msg,
  219. &data->vert_table);
  220. if (FAILED(hr))
  221. {
  222. msg::error("failed to compile vertex shader %s: %s\n", name.C(),
  223. error_msg ? error_msg->GetBufferPointer() : "error");
  224. msg::error("shader source:\n%s\n", vert);
  225. }
  226. data->m_dev->CreateVertexShader((DWORD *)shader_code->GetBufferPointer(),
  227. &data->vert_shader);
  228. shader_code->Release();
  229. #else
  230. shader_code = ShaderData::Patch(vert, ShaderType::Vertex);
  231. data->vert_id = glCreateShader(GL_VERTEX_SHADER);
  232. gl_code = shader_code.C();
  233. glShaderSource(data->vert_id, 1, &gl_code, nullptr);
  234. glCompileShader(data->vert_id);
  235. glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf);
  236. glGetShaderiv(data->vert_id, GL_COMPILE_STATUS, &status);
  237. if (status != GL_TRUE)
  238. {
  239. msg::error("failed to compile vertex shader %s: %s\n",
  240. name.C(), errbuf);
  241. msg::error("shader source:\n%s\n", shader_code.C());
  242. }
  243. else if (len > 16)
  244. {
  245. msg::debug("compile log for vertex shader %s: %s\n", name.C(), errbuf);
  246. msg::debug("shader source:\n%s\n", shader_code.C());
  247. }
  248. #endif
  249. /* Compile fragment shader */
  250. data->frag_crc = ShaderData::Hash(frag);
  251. #if defined USE_D3D9
  252. hr = D3DXCompileShader(frag, (UINT)strlen(frag), macros, nullptr, "main",
  253. "ps_3_0", 0, &shader_code, &error_msg,
  254. &data->frag_table);
  255. if (FAILED(hr))
  256. {
  257. msg::error("failed to compile fragment shader %s: %s\n", name.C(),
  258. error_msg ? error_msg->GetBufferPointer() : "error");
  259. msg::error("shader source:\n%s\n", frag);
  260. }
  261. data->m_dev->CreatePixelShader((DWORD *)shader_code->GetBufferPointer(),
  262. &data->frag_shader);
  263. shader_code->Release();
  264. #else
  265. shader_code = ShaderData::Patch(frag, ShaderType::Fragment);
  266. data->frag_id = glCreateShader(GL_FRAGMENT_SHADER);
  267. gl_code = shader_code.C();
  268. glShaderSource(data->frag_id, 1, &gl_code, nullptr);
  269. glCompileShader(data->frag_id);
  270. glGetShaderInfoLog(data->frag_id, sizeof(errbuf), &len, errbuf);
  271. glGetShaderiv(data->frag_id, GL_COMPILE_STATUS, &status);
  272. if (status != GL_TRUE)
  273. {
  274. msg::error("failed to compile fragment shader %s: %s\n",
  275. name.C(), errbuf);
  276. msg::error("shader source:\n%s\n", shader_code.C());
  277. }
  278. else if (len > 16)
  279. {
  280. msg::debug("compile log for fragment shader %s: %s\n",
  281. name.C(), errbuf);
  282. msg::debug("shader source:\n%s\n", shader_code.C());
  283. }
  284. #endif
  285. #if defined USE_D3D9
  286. /* FIXME: this is only debug code, we don't need it. */
  287. D3DXCONSTANTTABLE_DESC desc;
  288. data->frag_table->GetDesc(&desc);
  289. for (int i = 0; i < desc.Constants; i++)
  290. {
  291. D3DXCONSTANT_DESC cdesc;
  292. UINT count = 1;
  293. D3DXHANDLE h = data->frag_table->GetConstant(nullptr, i);
  294. data->frag_table->GetConstantDesc(h, &cdesc, &count);
  295. }
  296. data->vert_table->GetDesc(&desc);
  297. for (int i = 0; i < desc.Constants; i++)
  298. {
  299. D3DXCONSTANT_DESC cdesc;
  300. UINT count = 1;
  301. D3DXHANDLE h = data->vert_table->GetConstant(nullptr, i);
  302. data->frag_table->GetConstantDesc(h, &cdesc, &count);
  303. }
  304. #else
  305. /* Create program */
  306. data->prog_id = glCreateProgram();
  307. glAttachShader(data->prog_id, data->vert_id);
  308. glAttachShader(data->prog_id, data->frag_id);
  309. glLinkProgram(data->prog_id);
  310. glGetProgramInfoLog(data->prog_id, sizeof(errbuf), &len, errbuf);
  311. glGetProgramiv(data->prog_id, GL_LINK_STATUS, &status);
  312. if (status != GL_TRUE)
  313. {
  314. msg::error("failed to link program %s: %s\n", name.C(), errbuf);
  315. }
  316. else if (len > 16)
  317. {
  318. msg::debug("link log for program %s: %s\n", name.C(), errbuf);
  319. }
  320. GLint validated;
  321. glValidateProgram(data->prog_id);
  322. glGetProgramiv(data->prog_id, GL_VALIDATE_STATUS, &validated);
  323. if (validated != GL_TRUE)
  324. {
  325. msg::error("failed to validate program %s\n", name.C());
  326. }
  327. GLint num_attribs;
  328. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTES, &num_attribs);
  329. #if EMSCRIPTEN //WebGL doesn't support GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, so chose a default size value.
  330. GLint max_len = 256;
  331. #else
  332. GLint max_len;
  333. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
  334. #endif
  335. char* name_buffer = new char[max_len];
  336. for (int i = 0; i < num_attribs; ++i)
  337. {
  338. int attrib_len;
  339. int attrib_size;
  340. int attrib_type;
  341. glGetActiveAttrib(data->prog_id, i, max_len, &attrib_len, (GLint*)&attrib_size, (GLenum*)&attrib_type, name_buffer);
  342. String name(name_buffer);
  343. int index = -1;
  344. VertexUsage usage = VertexUsage::MAX;
  345. for (int j = 0; j < (int)VertexUsage::MAX; ++j)
  346. {
  347. if (name.starts_with(attribute_names[j]) ||
  348. name.starts_with(String(attribute_names[j]).to_lower()))
  349. {
  350. usage = VertexUsage(j);
  351. char* idx_ptr = name.C() + strlen(attribute_names[j]);
  352. index = strtol(idx_ptr, nullptr, 10);
  353. break;
  354. }
  355. }
  356. if (usage == VertexUsage::MAX || index == -1)
  357. {
  358. msg::error("unable to parse attribute semantic from name: %s\n",
  359. name_buffer);
  360. }
  361. else
  362. {
  363. GLint location = glGetAttribLocation(data->prog_id, name_buffer);
  364. uint64_t flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  365. flags |= (uint64_t)(uint16_t)index;
  366. // TODO: this is here just in case. Remove this once everything has been correctly tested
  367. #if _DEBUG
  368. if (data->attrib_locations.has_key(flags))
  369. {
  370. msg::error("error while parsing attribute semantics in %s\n",
  371. name.C());
  372. }
  373. #endif
  374. data->attrib_locations[flags] = location;
  375. }
  376. }
  377. delete[] name_buffer;
  378. #endif
  379. }
  380. int Shader::GetAttribCount() const
  381. {
  382. return data->attrib_locations.count();
  383. }
  384. ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const
  385. {
  386. ShaderAttrib ret;
  387. ret.m_flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  388. ret.m_flags |= (uint64_t)(uint16_t)index;
  389. #if defined USE_D3D9
  390. #else
  391. GLint l = -1;
  392. if (!data->attrib_locations.try_get(ret.m_flags, l))
  393. {
  394. /* Only spit an error once, we don’t need to flood the console. */
  395. if (!data->attrib_errors.has_key(ret.m_flags))
  396. {
  397. msg::error("attribute %s not found in shader %s\n",
  398. usage.ToString().C(), data->m_name.C());
  399. data->attrib_errors[ret.m_flags] = true;
  400. }
  401. }
  402. ret.m_flags |= (uint64_t)(uint32_t)l << 32;
  403. #endif
  404. return ret;
  405. }
  406. ShaderUniform Shader::GetUniformLocation(String const& uni) const
  407. {
  408. return GetUniformLocation(uni.C());
  409. }
  410. ShaderUniform Shader::GetUniformLocation(char const *uni) const
  411. {
  412. ShaderUniform ret;
  413. #if defined USE_D3D9
  414. /* Global variables are prefixed with "$" */
  415. String tmpname = String("$") + uni;
  416. D3DXCONSTANT_DESC cdesc;
  417. D3DXHANDLE hr;
  418. UINT count;
  419. count = 0;
  420. hr = data->frag_table->GetConstantByName(nullptr, tmpname.C());
  421. if (hr)
  422. data->frag_table->GetConstantDesc(hr, &cdesc, &count);
  423. if (count)
  424. {
  425. ret.frag = cdesc.RegisterIndex;
  426. ret.flags |= 1;
  427. }
  428. count = 0;
  429. hr = data->vert_table->GetConstantByName(nullptr, tmpname.C());
  430. if (hr)
  431. data->vert_table->GetConstantDesc(hr, &cdesc, &count);
  432. if (count)
  433. {
  434. ret.vert = cdesc.RegisterIndex;
  435. ret.flags |= 2;
  436. }
  437. #else
  438. ret.frag = (uintptr_t)glGetUniformLocation(data->prog_id, uni);
  439. ret.vert = 0;
  440. #endif
  441. return ret;
  442. }
  443. /*
  444. * Uniform setters for scalars
  445. */
  446. void Shader::SetUniform(ShaderUniform const &uni, int i)
  447. {
  448. #if defined USE_D3D9
  449. SetUniform(uni, ivec4(i, 0, 0, 0));
  450. #else
  451. glUniform1i((GLint)uni.frag, i);
  452. #endif
  453. }
  454. void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v)
  455. {
  456. #if defined USE_D3D9
  457. SetUniform(uni, ivec4(v, 0, 0));
  458. #else
  459. glUniform2i((GLint)uni.frag, v.x, v.y);
  460. #endif
  461. }
  462. void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v)
  463. {
  464. #if defined USE_D3D9
  465. SetUniform(uni, ivec4(v, 0));
  466. #else
  467. glUniform3i((GLint)uni.frag, v.x, v.y, v.z);
  468. #endif
  469. }
  470. void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v)
  471. {
  472. #if defined USE_D3D9
  473. if (uni.flags & 1)
  474. data->m_dev->SetPixelShaderConstantI((UINT)uni.frag, &v[0], 1);
  475. if (uni.flags & 2)
  476. data->m_dev->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1);
  477. #else
  478. glUniform4i((GLint)uni.frag, v.x, v.y, v.z, v.w);
  479. #endif
  480. }
  481. void Shader::SetUniform(ShaderUniform const &uni, float f)
  482. {
  483. #if defined USE_D3D9
  484. SetUniform(uni, vec4(f, 0, 0, 0));
  485. #else
  486. glUniform1f((GLint)uni.frag, f);
  487. #endif
  488. }
  489. void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v)
  490. {
  491. #if defined USE_D3D9
  492. SetUniform(uni, vec4(v, 0, 0));
  493. #else
  494. glUniform2fv((GLint)uni.frag, 1, &v[0]);
  495. #endif
  496. }
  497. void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v)
  498. {
  499. #if defined USE_D3D9
  500. SetUniform(uni, vec4(v, 0));
  501. #else
  502. glUniform3fv((GLint)uni.frag, 1, &v[0]);
  503. #endif
  504. }
  505. void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v)
  506. {
  507. #if defined USE_D3D9
  508. if (uni.flags & 1)
  509. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &v[0], 1);
  510. if (uni.flags & 2)
  511. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1);
  512. #else
  513. glUniform4fv((GLint)uni.frag, 1, &v[0]);
  514. #endif
  515. }
  516. void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m)
  517. {
  518. #if defined USE_D3D9
  519. /* FIXME: do we need padding here like for the mat3 version? */
  520. if (uni.flags & 1)
  521. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 1);
  522. if (uni.flags & 2)
  523. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1);
  524. #else
  525. glUniformMatrix2fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  526. #endif
  527. }
  528. void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m)
  529. {
  530. #if defined USE_D3D9
  531. /* Padding matrix columns is necessary on DirectX. We need to create
  532. * a new data structure; a 4×4 matrix will do. */
  533. mat4 tmp(m, 1.0f);
  534. if (uni.flags & 1)
  535. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &tmp[0][0], 3);
  536. if (uni.flags & 2)
  537. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3);
  538. #else
  539. glUniformMatrix3fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  540. #endif
  541. }
  542. void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
  543. {
  544. #if defined USE_D3D9
  545. if (uni.flags & 1)
  546. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 4);
  547. if (uni.flags & 2)
  548. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4);
  549. #else
  550. glUniformMatrix4fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]);
  551. #endif
  552. }
  553. void Shader::SetUniform(ShaderUniform const &uni, TextureUniform tex, int index)
  554. {
  555. #if defined USE_D3D9
  556. data->m_dev->SetTexture(index, (LPDIRECT3DTEXTURE9)tex.m_flags);
  557. data->m_dev->SetSamplerState(index, D3DSAMP_MAGFILTER, tex.m_attrib & 0xff);
  558. data->m_dev->SetSamplerState(index, D3DSAMP_MINFILTER, (tex.m_attrib >> 8) & 0xff);
  559. data->m_dev->SetSamplerState(index, D3DSAMP_MIPFILTER, (tex.m_attrib >> 16) & 0xff);
  560. #else
  561. glActiveTexture(GL_TEXTURE0 + index);
  562. //glEnable(GL_TEXTURE_2D);
  563. glBindTexture(GL_TEXTURE_2D, (int)tex.m_flags);
  564. SetUniform(uni, index);
  565. #endif
  566. }
  567. /*
  568. * Uniform setters for arrays
  569. */
  570. void Shader::SetUniform(ShaderUniform const &uni, array<float> const &v)
  571. {
  572. #if defined USE_D3D9
  573. /* FIXME: this will not work properly because we don't know how tell DX9
  574. * it's a bunch of floats instead of vec4. */
  575. if (uni.flags & 1)
  576. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  577. &v[0], v.count() / 4);
  578. if (uni.flags & 2)
  579. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  580. &v[0], v.count() / 4);
  581. #else
  582. glUniform1fv((GLint)uni.frag, (GLsizei)v.count(), &v[0]);
  583. #endif
  584. }
  585. void Shader::SetUniform(ShaderUniform const &uni, array<vec2> const &v)
  586. {
  587. #if defined USE_D3D9
  588. /* FIXME: this will not work properly because we don't know how tell DX9
  589. * it's a bunch of vec2 instead of vec4. */
  590. if (uni.flags & 1)
  591. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  592. &v[0][0], v.count() / 2);
  593. if (uni.flags & 2)
  594. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  595. &v[0][0], v.count() / 2);
  596. #else
  597. glUniform2fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  598. #endif
  599. }
  600. void Shader::SetUniform(ShaderUniform const &uni, array<vec3> const &v)
  601. {
  602. #if defined USE_D3D9
  603. /* FIXME: this will not work properly because we don't know how tell DX9
  604. * it's a bunch of vec3 instead of vec4. */
  605. if (uni.flags & 1)
  606. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  607. &v[0][0], v.count());
  608. if (uni.flags & 2)
  609. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  610. &v[0][0], v.count());
  611. #else
  612. glUniform3fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  613. #endif
  614. }
  615. void Shader::SetUniform(ShaderUniform const &uni, array<vec4> const &v)
  616. {
  617. #if defined USE_D3D9
  618. if (uni.flags & 1)
  619. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  620. &v[0][0], v.count());
  621. if (uni.flags & 2)
  622. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  623. &v[0][0], v.count());
  624. #else
  625. glUniform4fv((GLint)uni.frag, (GLsizei)v.count(), &v[0][0]);
  626. #endif
  627. }
  628. void Shader::Bind() const
  629. {
  630. #if defined USE_D3D9
  631. HRESULT hr;
  632. hr = data->m_dev->SetVertexShader(data->vert_shader);
  633. hr = data->m_dev->SetPixelShader(data->frag_shader);
  634. #else
  635. glUseProgram(data->prog_id);
  636. #endif
  637. }
  638. void Shader::Unbind() const
  639. {
  640. #if defined USE_D3D9
  641. HRESULT hr;
  642. hr = data->m_dev->SetVertexShader(nullptr);
  643. hr = data->m_dev->SetPixelShader(nullptr);
  644. #else
  645. /* FIXME: untested */
  646. glUseProgram(0);
  647. #endif
  648. }
  649. Shader::~Shader()
  650. {
  651. #if defined USE_D3D9
  652. data->vert_shader->Release();
  653. data->vert_table->Release();
  654. data->frag_shader->Release();
  655. data->frag_table->Release();
  656. #else
  657. glDetachShader(data->prog_id, data->vert_id);
  658. glDetachShader(data->prog_id, data->frag_id);
  659. glDeleteShader(data->vert_id);
  660. glDeleteShader(data->frag_id);
  661. glDeleteProgram(data->prog_id);
  662. #endif
  663. delete data;
  664. }
  665. /* Try to detect shader compiler features */
  666. int ShaderData::GetVersion()
  667. {
  668. static int version = 0;
  669. #if !defined USE_D3D9
  670. if (!version)
  671. {
  672. #if defined HAVE_GLES_2X
  673. /* GLES 2.x supports #version 100, that's all. */
  674. return 100;
  675. #else
  676. char buf[4096];
  677. GLsizei len;
  678. int id = glCreateShader(GL_VERTEX_SHADER);
  679. /* Can we compile 1.30 shaders? */
  680. char const *test130 =
  681. "#version 130\n"
  682. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  683. glShaderSource(id, 1, &test130, nullptr);
  684. glCompileShader(id);
  685. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  686. if (len <= 0)
  687. version = 130;
  688. /* If not, can we compile 1.20 shaders? */
  689. if (!version)
  690. {
  691. char const *test120 =
  692. "#version 120\n"
  693. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  694. glShaderSource(id, 1, &test120, nullptr);
  695. glCompileShader(id);
  696. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  697. if (len <= 0)
  698. version = 120;
  699. }
  700. /* Otherwise, assume we can compile 1.10 shaders. */
  701. if (!version)
  702. version = 110;
  703. glDeleteShader(id);
  704. #endif
  705. }
  706. #endif
  707. return version;
  708. }
  709. /*
  710. * Simple shader source patching for old GLSL versions.
  711. */
  712. String ShaderData::Patch(String const &code, ShaderType type)
  713. {
  714. int ver_driver = GetVersion();
  715. String patched_code = code;
  716. if (ver_driver >= 130)
  717. return patched_code;
  718. int ver_shader = 110;
  719. char *parser = strstr(patched_code.C(), "#version");
  720. if (parser)
  721. ver_shader = atoi(parser + strlen("#version"));
  722. /* This is GL ES, we only know version 100. */
  723. if (ver_shader > 100 && ver_driver == 100)
  724. {
  725. /* FIXME: this isn't elegant but honestly, we don't care, this
  726. * whole file is going to die soon. */
  727. char *p = strstr(patched_code.C(), "#version");
  728. if (p)
  729. {
  730. p += 8;
  731. while (*p == ' ')
  732. p++;
  733. if (p[0] == '1' && p[1] && p[2])
  734. p[1] = p[2] = '0';
  735. }
  736. }
  737. if (ver_shader > 120 && ver_driver <= 120)
  738. {
  739. char const *end = patched_code.C() + patched_code.count() + 1;
  740. /* Find main() */
  741. parser = strstr(patched_code.C(), "main");
  742. if (!parser) return patched_code;
  743. parser = strstr(parser, "(");
  744. if (!parser) return patched_code;
  745. parser = strstr(parser, ")");
  746. if (!parser) return patched_code;
  747. parser = strstr(parser, "{");
  748. if (!parser) return patched_code;
  749. char *main = parser + 1;
  750. /* Perform main() replaces */
  751. char const * const main_replaces[] =
  752. {
  753. #if 0
  754. "in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;",
  755. "in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;",
  756. "in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;",
  757. "in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;",
  758. "in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;",
  759. "in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;",
  760. "in vec2 in_MultiTexCoord0;",
  761. "vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;",
  762. "in vec2 in_MultiTexCoord1;",
  763. "vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;",
  764. "in vec2 in_MultiTexCoord2;",
  765. "vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;",
  766. "in vec2 in_MultiTexCoord3;",
  767. "vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;",
  768. "in vec2 in_MultiTexCoord4;",
  769. "vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;",
  770. "in vec2 in_MultiTexCoord5;",
  771. "vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;",
  772. "in vec2 in_MultiTexCoord6;",
  773. "vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;",
  774. "in vec2 in_MultiTexCoord7;",
  775. "vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;",
  776. #endif
  777. nullptr
  778. };
  779. for (char const * const *rep = main_replaces; rep[0]; rep += 2)
  780. {
  781. char *match = strstr(patched_code.C(), rep[0]);
  782. if (match && match < main)
  783. {
  784. size_t l0 = strlen(rep[0]);
  785. size_t l1 = strlen(rep[1]);
  786. memmove(main + l1, main, end - main);
  787. memcpy(main, rep[1], l1);
  788. memset(match, ' ', l0);
  789. main += l1;
  790. end += l1;
  791. }
  792. }
  793. /* Perform small replaces */
  794. char const * const fast_replaces[] =
  795. {
  796. "#version 130", "#version 120",
  797. "in vec2", type == ShaderType::Vertex ? "attribute vec2" : "varying vec2",
  798. "in vec3", type == ShaderType::Vertex ? "attribute vec3" : "varying vec3",
  799. "in vec4", type == ShaderType::Vertex ? "attribute vec4" : "varying vec4",
  800. "in mat4", type == ShaderType::Vertex ? "attribute mat4" : "varying mat4",
  801. "out vec2", "varying vec2",
  802. "out vec3", "varying vec3",
  803. "out vec4", "varying vec4",
  804. "out mat4", "varying mat4",
  805. nullptr
  806. };
  807. for (char const * const *rep = fast_replaces; rep[0]; rep += 2)
  808. {
  809. char *match;
  810. while ((match = strstr(patched_code.C(), rep[0])))
  811. {
  812. size_t l0 = strlen(rep[0]);
  813. size_t l1 = strlen(rep[1]);
  814. if (l1 > l0)
  815. memmove(match + l1, match + l0, (end - match) - l0);
  816. memcpy(match, rep[1], l1);
  817. if (l1 < l0)
  818. memset(match + l0, ' ', l1 - l0);
  819. end += l1 - l0;
  820. }
  821. }
  822. }
  823. patched_code.resize((int)strlen(patched_code.C()));
  824. return patched_code;
  825. }
  826. static const String g_ret = "\n";
  827. static const String g_eol = ";";
  828. static const String g_bop = "{";
  829. static const String g_bcl = "}";
  830. static const String g_tab = " ";
  831. //----
  832. String Shader::GetVariablePrefix(const ShaderVariable variable)
  833. {
  834. switch (variable.ToScalar())
  835. {
  836. case ShaderVariable::Attribute: return String("in_");
  837. case ShaderVariable::Uniform: return String("u_");
  838. case ShaderVariable::Varying: return String("pass_");
  839. case ShaderVariable::InOut:
  840. default: return String();
  841. }
  842. }
  843. //----
  844. String Shader::GetVariableQualifier(const ShaderVariable variable)
  845. {
  846. switch (variable.ToScalar())
  847. {
  848. case ShaderVariable::Attribute: return String("attribute");
  849. case ShaderVariable::Uniform: return String("uniform");
  850. case ShaderVariable::Varying: return String("varying");
  851. case ShaderVariable::InOut:
  852. default: return String();
  853. }
  854. }
  855. //----
  856. String Shader::GetFunctionQualifier(const ShaderVariable variable, const ShaderProgram program)
  857. {
  858. switch (program.ToScalar())
  859. {
  860. case ShaderProgram::Geometry:
  861. {
  862. //TODO : L O L ----------------
  863. return String();
  864. }
  865. case ShaderProgram::Vertex:
  866. {
  867. switch (variable.ToScalar())
  868. {
  869. case ShaderVariable::Attribute: return String("in");
  870. case ShaderVariable::Uniform: return String("in");
  871. case ShaderVariable::Varying: return String("inout");
  872. case ShaderVariable::InOut: return String("inout");
  873. default: return String();
  874. }
  875. return String();
  876. }
  877. case ShaderProgram::Pixel:
  878. {
  879. switch (variable.ToScalar())
  880. {
  881. case ShaderVariable::Attribute: return String("in");
  882. case ShaderVariable::Uniform: return String("in");
  883. case ShaderVariable::Varying: return String("in");
  884. case ShaderVariable::InOut: return String("inout");
  885. default: return String();
  886. }
  887. return String();
  888. }
  889. default:
  890. {
  891. return String();
  892. }
  893. }
  894. }
  895. //----
  896. String Shader::GetProgramQualifier(const ShaderProgram program)
  897. {
  898. switch (program.ToScalar())
  899. {
  900. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  901. case ShaderProgram::Vertex: return String("[vert.glsl]");
  902. case ShaderProgram::Pixel: return String("[frag.glsl]");
  903. default: return String();
  904. }
  905. }
  906. //----
  907. String Shader::GetProgramOutVariable(const ShaderProgram program)
  908. {
  909. switch (program.ToScalar())
  910. {
  911. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  912. case ShaderProgram::Vertex: return String("gl_Position");
  913. case ShaderProgram::Pixel: return String("gl_FragColor");
  914. default: return String();
  915. }
  916. }
  917. //----
  918. String Shader::GetProgramOutVariableLocal(const ShaderProgram program)
  919. {
  920. switch (program.ToScalar())
  921. {
  922. case ShaderProgram::Geometry: return String(); //TODO : L O L ---------
  923. case ShaderProgram::Vertex: return String("out_position");
  924. case ShaderProgram::Pixel: return String("out_frag_color");
  925. default: return String();
  926. }
  927. }
  928. //ShaderVar -------------------------------------------------------------------
  929. ShaderVar ShaderVar::GetShaderOut(ShaderProgram program)
  930. {
  931. switch (program.ToScalar())
  932. {
  933. case ShaderProgram::Geometry: //TODO : L O L ------------------------------
  934. default: ASSERT(false); return ShaderVar();
  935. case ShaderProgram::Vertex: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program));
  936. case ShaderProgram::Pixel: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program));
  937. }
  938. }
  939. //Shader Block implementation class -------------------------------------------
  940. void ShaderBlock::AddVar(ShaderVar const& var)
  941. {
  942. ShaderVariable qualifier = var.GetQualifier();
  943. String type = var.GetType();
  944. String name = Shader::GetVariablePrefix(qualifier) + var.m_name;
  945. ASSERT(!m_parameters[qualifier.ToScalar()].has_key(name));
  946. m_parameters[qualifier.ToScalar()][name] = type;
  947. }
  948. //----
  949. void ShaderBlock::AddCallParameters(map<String, String> const& variables, String& result)
  950. {
  951. array<String> keys = variables.keys();
  952. for (String key : keys)
  953. {
  954. if (result.count() > 0)
  955. result += ", ";
  956. result += key;
  957. }
  958. }
  959. //----
  960. void ShaderBlock::AddDefinitionParameters(const ShaderVariable type, const ShaderProgram program, map<String, String>& variables, String& result)
  961. {
  962. array<String> keys = variables.keys();
  963. for (String key : keys)
  964. {
  965. if (result.count() > 0)
  966. result += ", ";
  967. result += Shader::GetFunctionQualifier(type, program) + " ";
  968. result += variables[key];
  969. result += String(" ");
  970. result += key;
  971. }
  972. }
  973. //----
  974. void ShaderBlock::Build(const ShaderProgram program, String& call, String& function)
  975. {
  976. ASSERT(m_name.count());
  977. ASSERT(m_parameters[ShaderVariable::InOut].count());
  978. //Build call in main
  979. String call_name = String("Call_") + m_name;
  980. call = call_name + "(";
  981. String call_parameters;
  982. for (int i = 0; i < ShaderVariable::MAX; i++)
  983. AddCallParameters(/*(ShaderVariable)i, */m_parameters[i], call_parameters);
  984. call += call_parameters + ");";
  985. //Build function declaration
  986. function = String("void ") + call_name + "(";
  987. String def_parameters;
  988. for (int i = 0; i < ShaderVariable::MAX; i++)
  989. AddDefinitionParameters((ShaderVariable)i, program, m_parameters[i], def_parameters);
  990. function += def_parameters + ")" + g_ret +
  991. "{" + g_ret +
  992. m_code_main + ((m_code_main.ends_with(g_ret)) ? (String()) : (g_ret)) +
  993. "}";
  994. }
  995. //Shader Builder implementation class -----------------------------------------
  996. ShaderBuilder::ShaderBuilder(String const& name, String const& version)
  997. : m_name(name), m_version(version)
  998. {
  999. ASSERT(name.count());
  1000. ASSERT(version.count());
  1001. }
  1002. //----
  1003. ShaderBuilder::~ShaderBuilder()
  1004. {
  1005. }
  1006. //----
  1007. String const& ShaderBuilder::GetName()
  1008. {
  1009. return m_name;
  1010. }
  1011. //----
  1012. ShaderBuilder& ShaderBuilder::operator<<(const ShaderProgram program)
  1013. {
  1014. m_current_program = program;
  1015. return *this;
  1016. }
  1017. //----
  1018. ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock* block)
  1019. {
  1020. ASSERT(m_current_program != ShaderProgram::MAX);
  1021. m_blocks[m_current_program.ToScalar()].push_unique(block);
  1022. return *this;
  1023. }
  1024. //----
  1025. ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock const& block)
  1026. {
  1027. ASSERT(m_current_program != ShaderProgram::MAX);
  1028. m_blocks[m_current_program.ToScalar()].push_unique(new ShaderBlock(block));
  1029. return *this;
  1030. }
  1031. //----
  1032. String ShaderBuilder::AddSlotOutVariableLocal(const ShaderProgram program)
  1033. {
  1034. ShaderVariable var = ShaderVariable::InOut;
  1035. String result = Shader::GetProgramOutVariableLocal(program);
  1036. switch (program.ToScalar())
  1037. {
  1038. case ShaderProgram::Geometry:
  1039. {
  1040. //TODO : L O L ----------------
  1041. break;
  1042. }
  1043. case ShaderProgram::Vertex:
  1044. {
  1045. m_parameters[program.ToScalar()][var.ToScalar()][result] = "vec4";
  1046. break;
  1047. }
  1048. case ShaderProgram::Pixel:
  1049. {
  1050. m_parameters[program.ToScalar()][var.ToScalar()][result] = "vec4";
  1051. break;
  1052. }
  1053. default:
  1054. {
  1055. break;
  1056. }
  1057. }
  1058. return result;
  1059. }
  1060. //----
  1061. void ShaderBuilder::MergeParameters(map<String, String>& variables, map<String, String>& merged)
  1062. {
  1063. array<String> keys = variables.keys();
  1064. for (String key : keys)
  1065. {
  1066. bool has_key = merged.has_key(key);
  1067. //Key exists, check the type to make sure it's the same
  1068. ASSERT(!has_key || (has_key && merged[key] == variables[key]),
  1069. "has_key=%d, key=%s merged[key]=%s, variables[key]=%s\n",
  1070. (int)has_key, key.C(), merged[key].C(), variables[key].C());
  1071. //does not exist, had it
  1072. if (!has_key)
  1073. merged[key] = variables[key];
  1074. }
  1075. }
  1076. //----
  1077. void ShaderBuilder::Build(String& code)
  1078. {
  1079. //Cleanup first
  1080. for (int prog = 0; prog < ShaderProgram::MAX; prog++)
  1081. for (int var = 0; var < ShaderVariable::MAX; var++)
  1082. m_parameters[prog][var].empty();
  1083. //Start building
  1084. for (int prog = 0; prog < ShaderProgram::MAX; prog++)
  1085. {
  1086. //Add default local out in merged variables
  1087. String out_local_var = AddSlotOutVariableLocal((ShaderProgram)prog);
  1088. if (!out_local_var.count())
  1089. continue;
  1090. //Merge all variables
  1091. for (int var = 0; var < ShaderVariable::MAX; var++)
  1092. for (int block = 0; block < m_blocks[prog].count(); block++)
  1093. MergeParameters(m_blocks[prog][block]->m_parameters[var], m_parameters[prog][var]);
  1094. //Actually write code
  1095. code += Shader::GetProgramQualifier((ShaderProgram)prog) + g_ret;
  1096. //Add actual code
  1097. code += String("#version ") + m_version + g_ret + g_ret;
  1098. //Added shader variables
  1099. for (int var = 0; var < ShaderVariable::InOut; var++)
  1100. {
  1101. array<String> keys = m_parameters[prog][var].keys();
  1102. if (keys.count())
  1103. {
  1104. code += String("//- ") + Shader::GetVariableQualifier((ShaderVariable)var) + " ----" + g_ret;
  1105. for (String key : keys)
  1106. {
  1107. code += Shader::GetVariableQualifier((ShaderVariable)var) + " ";
  1108. code += m_parameters[prog][var][key] + " " + key + ";" + g_ret;
  1109. }
  1110. if (var + 1 < ShaderVariable::InOut)
  1111. code += g_ret;
  1112. }
  1113. }
  1114. code += g_ret;
  1115. //Build Blocks code and add it
  1116. array<String> calls;
  1117. for (int block = 0; block < m_blocks[prog].count(); block++)
  1118. {
  1119. String call;
  1120. String function;
  1121. m_blocks[prog][block]->Build(ShaderProgram(prog), call, function);
  1122. calls << call;
  1123. if (m_blocks[prog][block]->m_code_custom.count())
  1124. {
  1125. code += String("//- ") + m_blocks[prog][block]->GetName() + " custom code ----" + g_ret;
  1126. code += m_blocks[prog][block]->m_code_custom + g_ret + g_ret;
  1127. }
  1128. code += String("//- ") + m_blocks[prog][block]->GetName() + " main code ----" + g_ret;
  1129. code += function + g_ret + g_ret;
  1130. }
  1131. //Added main definition
  1132. code += String("//- Main ----") + g_ret +
  1133. String("void main(void)") + g_ret + "{" + g_ret;
  1134. //Add local variables
  1135. int var = ShaderVariable::InOut;
  1136. array<String> keys = m_parameters[prog][var].keys();
  1137. for (String key : keys)
  1138. {
  1139. if (keys.count())
  1140. {
  1141. code += g_tab + m_parameters[prog][var][key] + " " + key + ";" + g_ret;
  1142. }
  1143. }
  1144. code += g_ret;
  1145. //Add calls
  1146. code += g_tab + String("//- Calls ----") + g_ret;
  1147. for (String call : calls)
  1148. code += g_tab + call + g_ret;
  1149. code += g_ret;
  1150. code += g_tab + Shader::GetProgramOutVariable((ShaderProgram)prog) + " = " + out_local_var + ";" + g_ret +
  1151. String("}") + g_ret + g_ret;
  1152. }
  1153. }
  1154. } /* namespace lol */