Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1276 строки
37 KiB

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