1031 linhas
31 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  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 <lol/main.h>
  31. #include "lolgl.h"
  32. using namespace std;
  33. namespace lol
  34. {
  35. struct ShaderType
  36. {
  37. enum Value
  38. {
  39. Vertex = 1,
  40. Fragment,
  41. Geometry,
  42. TessControl,
  43. TessEval,
  44. }
  45. m_value;
  46. inline ShaderType(Value v) : m_value(v) {}
  47. inline ShaderType(int v) : m_value((Value)v) {}
  48. inline operator Value() { return m_value; }
  49. };
  50. static const char* attribute_names[] =
  51. {
  52. "in_Position",
  53. "in_BlendWeight",
  54. "in_BlendIndices",
  55. "in_Normal",
  56. "in_PointSize",
  57. "in_TexCoord",
  58. "in_TexCoordExt",
  59. "in_Tangent",
  60. "in_Binormal",
  61. "in_TessFactor",
  62. "in_PositionT",
  63. "in_Color",
  64. "in_Fog",
  65. "in_Depth",
  66. "in_Sample"
  67. };
  68. /*
  69. * Shader implementation class
  70. */
  71. class ShaderData
  72. {
  73. friend class Shader;
  74. private:
  75. String m_name;
  76. #if defined USE_D3D9
  77. IDirect3DDevice9 *m_dev;
  78. IDirect3DVertexShader9 *vert_shader;
  79. IDirect3DPixelShader9 *frag_shader;
  80. ID3DXConstantTable *vert_table, *frag_table;
  81. #elif defined _XBOX
  82. D3DDevice *m_dev;
  83. D3DVertexShader *vert_shader;
  84. D3DPixelShader *frag_shader;
  85. ID3DXConstantTable *vert_table, *frag_table;
  86. #elif !defined __CELLOS_LV2__
  87. GLuint prog_id, vert_id, frag_id;
  88. // Benlitz: using a simple array could be faster since there is never more than a few attribute locations to store
  89. map<uint64_t, GLint> attrib_locations;
  90. map<uint64_t, bool> attrib_errors;
  91. #else
  92. CGprogram vert_id, frag_id;
  93. #endif
  94. uint32_t vert_crc, frag_crc;
  95. /* Shader patcher */
  96. static int GetVersion();
  97. static String Patch(String const &code, ShaderType type);
  98. /* Global shader cache */
  99. static Shader *shaders[];
  100. static hash<char const *> Hash;
  101. static int nshaders;
  102. };
  103. Shader *ShaderData::shaders[256];
  104. hash<char const *> ShaderData::Hash;
  105. int ShaderData::nshaders = 0;
  106. /*
  107. * Public Shader class
  108. */
  109. Shader *Shader::Create(String const &name, String const &code)
  110. {
  111. String src = String("\n") + code;
  112. /* Parse the crap */
  113. array<char const *, char const *> sections;
  114. char *key = nullptr;
  115. for (char *parser = src.C(); *parser; )
  116. {
  117. if (key == nullptr && (parser[0] == '\n' || parser[0] == '\r')
  118. && parser[1] == '[')
  119. {
  120. *parser = '\0';
  121. parser += 2;
  122. key = parser;
  123. }
  124. else if (key && parser[0] == ']')
  125. {
  126. *parser++ = '\0';
  127. }
  128. else if (key && (parser[0] == '\n' || parser[0] == '\r'))
  129. {
  130. sections.Push(key, parser);
  131. parser++;
  132. key = nullptr;
  133. }
  134. else
  135. {
  136. parser++;
  137. }
  138. }
  139. char const *vert = nullptr, *frag = nullptr;
  140. for (int i = 0; i < sections.Count(); i++)
  141. {
  142. #if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
  143. if (!strcmp(sections[i].m1, "vert.glsl"))
  144. vert = sections[i].m2;
  145. if (!strcmp(sections[i].m1, "frag.glsl"))
  146. frag = sections[i].m2;
  147. #else
  148. if (!strcmp(sections[i].m1, "vert.hlsl"))
  149. vert = sections[i].m2;
  150. if (!strcmp(sections[i].m1, "frag.hlsl"))
  151. frag = sections[i].m2;
  152. #endif
  153. }
  154. /* FIXME: we don’t know how to handle these yet. */
  155. if (!vert)
  156. Log::Error("no vertex shader found in %s… sorry, I’m gonna crash now.\n",
  157. name.C());
  158. if (!frag)
  159. Log::Error("no fragment shader found in %s… sorry, I’m gonna crash now.\n",
  160. name.C());
  161. uint32_t new_vert_crc = ShaderData::Hash(vert);
  162. uint32_t new_frag_crc = ShaderData::Hash(frag);
  163. for (int n = 0; n < ShaderData::nshaders; n++)
  164. {
  165. if (ShaderData::shaders[n]->data->vert_crc == new_vert_crc
  166. && ShaderData::shaders[n]->data->frag_crc == new_frag_crc)
  167. {
  168. return ShaderData::shaders[n];
  169. }
  170. }
  171. Shader *ret = new Shader(name, vert, frag);
  172. ShaderData::shaders[ShaderData::nshaders] = ret;
  173. ShaderData::nshaders++;
  174. return ret;
  175. }
  176. void Shader::Destroy(Shader *shader)
  177. {
  178. /* XXX: do nothing! the shader should remain in cache */
  179. UNUSED(shader);
  180. }
  181. Shader::Shader(String const &name,
  182. char const *vert, char const *frag)
  183. : data(new ShaderData())
  184. {
  185. data->m_name = name;
  186. #if defined USE_D3D9 || defined _XBOX
  187. ID3DXBuffer *shader_code, *error_msg;
  188. HRESULT hr;
  189. D3DXMACRO macros[] =
  190. {
  191. #if defined _XBOX
  192. { "_XBOX", "1" },
  193. #endif
  194. { nullptr, nullptr }
  195. };
  196. #elif !defined __CELLOS_LV2__
  197. char errbuf[4096];
  198. String shader_code;
  199. GLchar const *gl_code;
  200. GLint status;
  201. GLsizei len;
  202. #else
  203. /* Initialise the runtime shader compiler. FIXME: this needs only
  204. * to be done once. */
  205. cgRTCgcInit();
  206. #endif
  207. /* Compile vertex shader */
  208. data->vert_crc = ShaderData::Hash(vert);
  209. #if defined USE_D3D9 || defined _XBOX
  210. # if defined USE_D3D9
  211. data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
  212. # elif defined _XBOX
  213. data->m_dev = (D3DDevice *)g_renderer->GetDevice();
  214. # endif
  215. hr = D3DXCompileShader(vert, (UINT)strlen(vert), macros, nullptr, "main",
  216. "vs_3_0", 0, &shader_code, &error_msg,
  217. &data->vert_table);
  218. if (FAILED(hr))
  219. {
  220. Log::Error("failed to compile vertex shader %s: %s\n", name.C(),
  221. error_msg ? error_msg->GetBufferPointer() : "error");
  222. Log::Error("shader source:\n%s\n", vert);
  223. }
  224. data->m_dev->CreateVertexShader((DWORD *)shader_code->GetBufferPointer(),
  225. &data->vert_shader);
  226. shader_code->Release();
  227. #elif !defined __CELLOS_LV2__
  228. shader_code = ShaderData::Patch(vert, ShaderType::Vertex);
  229. data->vert_id = glCreateShader(GL_VERTEX_SHADER);
  230. gl_code = shader_code.C();
  231. glShaderSource(data->vert_id, 1, &gl_code, nullptr);
  232. glCompileShader(data->vert_id);
  233. glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf);
  234. glGetShaderiv(data->vert_id, GL_COMPILE_STATUS, &status);
  235. if (status != GL_TRUE)
  236. {
  237. Log::Error("failed to compile vertex shader %s: %s\n",
  238. name.C(), errbuf);
  239. Log::Error("shader source:\n%s\n", shader_code.C());
  240. }
  241. else if (len > 16)
  242. {
  243. Log::Debug("compile log for vertex shader %s: %s\n", name.C(), errbuf);
  244. Log::Debug("shader source:\n%s\n", shader_code.C());
  245. }
  246. #else
  247. data->vert_id = cgCreateProgram(cgCreateContext(), CG_SOURCE, vert,
  248. cgGLGetLatestProfile(CG_GL_VERTEX),
  249. nullptr, nullptr);
  250. if (data->vert_id == nullptr)
  251. {
  252. Log::Error("failed to compile vertex shader %s\n", name.C());
  253. Log::Error("shader source:\n%s\n", vert);
  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. #elif !defined __CELLOS_LV2__
  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. #else
  292. data->frag_id = cgCreateProgram(cgCreateContext(), CG_SOURCE, frag,
  293. cgGLGetLatestProfile(CG_GL_FRAGMENT),
  294. nullptr, nullptr);
  295. if (data->frag_id == nullptr)
  296. {
  297. Log::Error("failed to compile fragment shader %s\n", name.C());
  298. Log::Error("shader source:\n%s\n", frag);
  299. }
  300. #endif
  301. #if defined USE_D3D9 || defined _XBOX
  302. /* FIXME: this is only debug code, we don't need it. */
  303. D3DXCONSTANTTABLE_DESC desc;
  304. data->frag_table->GetDesc(&desc);
  305. for (int i = 0; i < desc.Constants; i++)
  306. {
  307. D3DXCONSTANT_DESC cdesc;
  308. UINT count = 1;
  309. D3DXHANDLE h = data->frag_table->GetConstant(nullptr, i);
  310. data->frag_table->GetConstantDesc(h, &cdesc, &count);
  311. }
  312. data->vert_table->GetDesc(&desc);
  313. for (int i = 0; i < desc.Constants; i++)
  314. {
  315. D3DXCONSTANT_DESC cdesc;
  316. UINT count = 1;
  317. D3DXHANDLE h = data->vert_table->GetConstant(nullptr, i);
  318. data->frag_table->GetConstantDesc(h, &cdesc, &count);
  319. }
  320. #elif !defined __CELLOS_LV2__
  321. /* Create program */
  322. data->prog_id = glCreateProgram();
  323. glAttachShader(data->prog_id, data->vert_id);
  324. glAttachShader(data->prog_id, data->frag_id);
  325. glLinkProgram(data->prog_id);
  326. glGetProgramInfoLog(data->prog_id, sizeof(errbuf), &len, errbuf);
  327. glGetProgramiv(data->prog_id, GL_LINK_STATUS, &status);
  328. if (status != GL_TRUE)
  329. {
  330. Log::Error("failed to link program %s: %s\n", name.C(), errbuf);
  331. }
  332. else if (len > 16)
  333. {
  334. Log::Debug("link log for program %s: %s\n", name.C(), errbuf);
  335. }
  336. GLint validated;
  337. glValidateProgram(data->prog_id);
  338. glGetProgramiv(data->prog_id, GL_VALIDATE_STATUS, &validated);
  339. if (validated != GL_TRUE)
  340. {
  341. Log::Error("failed to validate program %s\n", name.C());
  342. }
  343. GLint num_attribs;
  344. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTES, &num_attribs);
  345. #if EMSCRIPTEN //WebGL doesn't support GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, so chose a default size value.
  346. GLint max_len = 256;
  347. #else
  348. GLint max_len;
  349. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
  350. #endif
  351. char* name_buffer = new char[max_len];
  352. for (int i = 0; i < num_attribs; ++i)
  353. {
  354. int attrib_len;
  355. int attrib_size;
  356. int attrib_type;
  357. glGetActiveAttrib(data->prog_id, i, max_len, &attrib_len, (GLint*)&attrib_size, (GLenum*)&attrib_type, name_buffer);
  358. String name(name_buffer);
  359. int index = -1;
  360. VertexUsage usage = VertexUsage::MAX;
  361. for (int j = 0; j < (int)VertexUsage::MAX; ++j)
  362. {
  363. if (name.StartsWith(attribute_names[j]))
  364. {
  365. usage = VertexUsage(j);
  366. char* idx_ptr = name.C() + strlen(attribute_names[j]);
  367. index = strtol(idx_ptr, nullptr, 10);
  368. break;
  369. }
  370. }
  371. if (usage == VertexUsage::MAX || index == -1)
  372. {
  373. Log::Error("unable to parse attribute semantic from name: %s\n",
  374. name_buffer);
  375. }
  376. else
  377. {
  378. GLint location = glGetAttribLocation(data->prog_id, name_buffer);
  379. uint64_t flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  380. flags |= (uint64_t)(uint16_t)index;
  381. // TODO: this is here just in case. Remove this once everything has been correctly tested
  382. #if _DEBUG
  383. if (data->attrib_locations.HasKey(flags))
  384. {
  385. Log::Error("error while parsing attribute semantics in %s\n",
  386. name.C());
  387. }
  388. #endif
  389. data->attrib_locations[flags] = location;
  390. }
  391. }
  392. delete[] name_buffer;
  393. #endif
  394. }
  395. int Shader::GetAttribCount() const
  396. {
  397. #if !defined __CELLOS_LV2__
  398. return data->attrib_locations.Count();
  399. #else
  400. // TODO
  401. return 0;
  402. #endif
  403. }
  404. ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const
  405. {
  406. ShaderAttrib ret;
  407. ret.m_flags = (uint64_t)(uint16_t)usage.ToScalar() << 16;
  408. ret.m_flags |= (uint64_t)(uint16_t)index;
  409. #if defined USE_D3D9 || defined _XBOX
  410. #elif !defined __CELLOS_LV2__
  411. GLint l = -1;
  412. if (!data->attrib_locations.TryGetValue(ret.m_flags, l))
  413. {
  414. /* Only spit an error once, we don’t need to flood the console. */
  415. if (!data->attrib_errors.HasKey(ret.m_flags))
  416. {
  417. Log::Error("attribute %s not found in shader %s\n",
  418. usage.ToString().C(), data->m_name.C());
  419. data->attrib_errors[ret.m_flags] = true;
  420. }
  421. }
  422. ret.m_flags |= (uint64_t)(uint32_t)l << 32;
  423. #else
  424. /* FIXME: can we do this at all on the PS3? */
  425. #endif
  426. return ret;
  427. }
  428. ShaderUniform Shader::GetUniformLocation(char const *uni) const
  429. {
  430. ShaderUniform ret;
  431. #if defined USE_D3D9 || defined _XBOX
  432. /* Global variables are prefixed with "$" */
  433. String tmpname = String("$") + uni;
  434. D3DXCONSTANT_DESC cdesc;
  435. D3DXHANDLE hr;
  436. UINT count;
  437. count = 0;
  438. hr = data->frag_table->GetConstantByName(nullptr, tmpname.C());
  439. if (hr)
  440. data->frag_table->GetConstantDesc(hr, &cdesc, &count);
  441. if (count)
  442. {
  443. ret.frag = cdesc.RegisterIndex;
  444. ret.flags |= 1;
  445. }
  446. count = 0;
  447. hr = data->vert_table->GetConstantByName(nullptr, tmpname.C());
  448. if (hr)
  449. data->vert_table->GetConstantDesc(hr, &cdesc, &count);
  450. if (count)
  451. {
  452. ret.vert = cdesc.RegisterIndex;
  453. ret.flags |= 2;
  454. }
  455. #elif !defined __CELLOS_LV2__
  456. ret.frag = (uintptr_t)glGetUniformLocation(data->prog_id, uni);
  457. ret.vert = 0;
  458. #else
  459. ret.frag = (uintptr_t)cgGetNamedParameter(data->frag_id, uni);
  460. ret.vert = (uintptr_t)cgGetNamedParameter(data->vert_id, uni);
  461. #endif
  462. return ret;
  463. }
  464. /*
  465. * Uniform setters for scalars
  466. */
  467. void Shader::SetUniform(ShaderUniform const &uni, int i)
  468. {
  469. #if defined USE_D3D9 || defined _XBOX
  470. SetUniform(uni, ivec4(i, 0, 0, 0));
  471. #elif !defined __CELLOS_LV2__
  472. glUniform1i(uni.frag, i);
  473. #else
  474. /* FIXME: does this exist at all? cgGLSetParameter1i doesn't. */
  475. #endif
  476. }
  477. void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v)
  478. {
  479. #if defined USE_D3D9 || defined _XBOX
  480. SetUniform(uni, ivec4(v, 0, 0));
  481. #elif !defined __CELLOS_LV2__
  482. glUniform2i(uni.frag, v.x, v.y);
  483. #else
  484. /* FIXME: does this exist at all? */
  485. #endif
  486. }
  487. void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v)
  488. {
  489. #if defined USE_D3D9 || defined _XBOX
  490. SetUniform(uni, ivec4(v, 0));
  491. #elif !defined __CELLOS_LV2__
  492. glUniform3i(uni.frag, v.x, v.y, v.z);
  493. #else
  494. /* FIXME: does this exist at all? */
  495. #endif
  496. }
  497. void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v)
  498. {
  499. #if defined USE_D3D9 || defined _XBOX
  500. if (uni.flags & 1)
  501. data->m_dev->SetPixelShaderConstantI((UINT)uni.frag, &v[0], 1);
  502. if (uni.flags & 2)
  503. data->m_dev->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1);
  504. #elif !defined __CELLOS_LV2__
  505. glUniform4i(uni.frag, v.x, v.y, v.z, v.w);
  506. #else
  507. /* FIXME: does this exist at all? */
  508. #endif
  509. }
  510. void Shader::SetUniform(ShaderUniform const &uni, float f)
  511. {
  512. #if defined USE_D3D9 || defined _XBOX
  513. SetUniform(uni, vec4(f, 0, 0, 0));
  514. #elif !defined __CELLOS_LV2__
  515. glUniform1f(uni.frag, f);
  516. #else
  517. if (uni.frag)
  518. cgGLSetParameter1f((CGparameter)uni.frag, f);
  519. if (uni.vert)
  520. cgGLSetParameter1f((CGparameter)uni.vert, f);
  521. #endif
  522. }
  523. void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v)
  524. {
  525. #if defined USE_D3D9 || defined _XBOX
  526. SetUniform(uni, vec4(v, 0, 0));
  527. #elif !defined __CELLOS_LV2__
  528. glUniform2fv(uni.frag, 1, &v[0]);
  529. #else
  530. if (uni.frag)
  531. cgGLSetParameter2fv((CGparameter)uni.frag, &v[0]);
  532. if (uni.vert)
  533. cgGLSetParameter2fv((CGparameter)uni.vert, &v[0]);
  534. #endif
  535. }
  536. void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v)
  537. {
  538. #if defined USE_D3D9 || defined _XBOX
  539. SetUniform(uni, vec4(v, 0));
  540. #elif !defined __CELLOS_LV2__
  541. glUniform3fv(uni.frag, 1, &v[0]);
  542. #else
  543. if (uni.frag)
  544. cgGLSetParameter3fv((CGparameter)uni.frag, &v[0]);
  545. if (uni.vert)
  546. cgGLSetParameter3fv((CGparameter)uni.vert, &v[0]);
  547. #endif
  548. }
  549. void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v)
  550. {
  551. #if defined USE_D3D9 || defined _XBOX
  552. if (uni.flags & 1)
  553. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &v[0], 1);
  554. if (uni.flags & 2)
  555. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1);
  556. #elif !defined __CELLOS_LV2__
  557. glUniform4fv(uni.frag, 1, &v[0]);
  558. #else
  559. if (uni.frag)
  560. cgGLSetParameter4fv((CGparameter)uni.frag, &v[0]);
  561. if (uni.vert)
  562. cgGLSetParameter4fv((CGparameter)uni.vert, &v[0]);
  563. #endif
  564. }
  565. void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m)
  566. {
  567. #if defined USE_D3D9 || defined _XBOX
  568. /* FIXME: do we need padding here like for the mat3 version? */
  569. if (uni.flags & 1)
  570. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 1);
  571. if (uni.flags & 2)
  572. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1);
  573. #elif !defined __CELLOS_LV2__
  574. glUniformMatrix2fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  575. #else
  576. mat4 tmp(m, 1.0f, 1.0f);
  577. if (uni.frag)
  578. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  579. if (uni.vert)
  580. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  581. #endif
  582. }
  583. void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m)
  584. {
  585. #if defined USE_D3D9 || defined _XBOX
  586. /* Padding matrix columns is necessary on DirectX. We need to create
  587. * a new data structure; a 4×4 matrix will do. */
  588. mat4 tmp(m, 1.0f);
  589. if (uni.flags & 1)
  590. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &tmp[0][0], 3);
  591. if (uni.flags & 2)
  592. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3);
  593. #elif !defined __CELLOS_LV2__
  594. glUniformMatrix3fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  595. #else
  596. /* FIXME: check it's the proper way to do this */
  597. mat4 tmp(m, 1.0f);
  598. if (uni.frag)
  599. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  600. if (uni.vert)
  601. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  602. #endif
  603. }
  604. void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
  605. {
  606. #if defined USE_D3D9 || defined _XBOX
  607. if (uni.flags & 1)
  608. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 4);
  609. if (uni.flags & 2)
  610. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4);
  611. #elif !defined __CELLOS_LV2__
  612. glUniformMatrix4fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  613. #else
  614. if (uni.frag)
  615. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  616. if (uni.vert)
  617. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  618. #endif
  619. }
  620. void Shader::SetUniform(ShaderUniform const &uni, TextureUniform tex, int index)
  621. {
  622. #if defined USE_D3D9 || defined _XBOX
  623. data->m_dev->SetTexture(index, (LPDIRECT3DTEXTURE9)tex.m_flags);
  624. data->m_dev->SetSamplerState(index, D3DSAMP_MAGFILTER, tex.m_attrib & 0xff);
  625. data->m_dev->SetSamplerState(index, D3DSAMP_MINFILTER, (tex.m_attrib >> 8) & 0xff);
  626. data->m_dev->SetSamplerState(index, D3DSAMP_MIPFILTER, (tex.m_attrib >> 16) & 0xff);
  627. #elif !defined __CELLOS_LV2__
  628. glActiveTexture(GL_TEXTURE0 + index);
  629. //glEnable(GL_TEXTURE_2D);
  630. glBindTexture(GL_TEXTURE_2D, (int)tex.m_flags);
  631. SetUniform(uni, index);
  632. #else
  633. /* FIXME: unimplemented */
  634. #endif
  635. }
  636. /*
  637. * Uniform setters for arrays
  638. */
  639. void Shader::SetUniform(ShaderUniform const &uni, array<float> const &v)
  640. {
  641. #if defined USE_D3D9 || defined _XBOX
  642. /* FIXME: this will not work properly because we don't know how tell DX9
  643. * it's a bunch of floats instead of vec4. */
  644. if (uni.flags & 1)
  645. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  646. &v[0], v.Count() / 4);
  647. if (uni.flags & 2)
  648. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  649. &v[0], v.Count() / 4);
  650. #elif !defined __CELLOS_LV2__
  651. glUniform1fv(uni.frag, v.Count(), &v[0]);
  652. #else
  653. if (uni.frag)
  654. cgGLSetParameterArray1f((CGparameter)uni.frag,
  655. 0, v.Count(), &v[0]);
  656. if (uni.vert)
  657. cgGLSetParameterArray1f((CGparameter)uni.vert,
  658. 0, v.Count(), &v[0]);
  659. #endif
  660. }
  661. void Shader::SetUniform(ShaderUniform const &uni, array<vec2> const &v)
  662. {
  663. #if defined USE_D3D9 || defined _XBOX
  664. /* FIXME: this will not work properly because we don't know how tell DX9
  665. * it's a bunch of vec2 instead of vec4. */
  666. if (uni.flags & 1)
  667. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  668. &v[0][0], v.Count() / 2);
  669. if (uni.flags & 2)
  670. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  671. &v[0][0], v.Count() / 2);
  672. #elif !defined __CELLOS_LV2__
  673. glUniform2fv(uni.frag, v.Count(), &v[0][0]);
  674. #else
  675. if (uni.frag)
  676. cgGLSetParameterArray2f((CGparameter)uni.frag,
  677. 0, v.Count(), &v[0][0]);
  678. if (uni.vert)
  679. cgGLSetParameterArray2f((CGparameter)uni.vert,
  680. 0, v.Count(), &v[0][0]);
  681. #endif
  682. }
  683. void Shader::SetUniform(ShaderUniform const &uni, array<vec3> const &v)
  684. {
  685. #if defined USE_D3D9 || defined _XBOX
  686. /* FIXME: this will not work properly because we don't know how tell DX9
  687. * it's a bunch of vec3 instead of vec4. */
  688. if (uni.flags & 1)
  689. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  690. &v[0][0], v.Count());
  691. if (uni.flags & 2)
  692. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  693. &v[0][0], v.Count());
  694. #elif !defined __CELLOS_LV2__
  695. glUniform3fv(uni.frag, v.Count(), &v[0][0]);
  696. #else
  697. if (uni.frag)
  698. cgGLSetParameterArray3f((CGparameter)uni.frag,
  699. 0, v.Count(), &v[0][0]);
  700. if (uni.vert)
  701. cgGLSetParameterArray3f((CGparameter)uni.vert,
  702. 0, v.Count(), &v[0][0]);
  703. #endif
  704. }
  705. void Shader::SetUniform(ShaderUniform const &uni, array<vec4> const &v)
  706. {
  707. #if defined USE_D3D9 || defined _XBOX
  708. if (uni.flags & 1)
  709. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  710. &v[0][0], v.Count());
  711. if (uni.flags & 2)
  712. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  713. &v[0][0], v.Count());
  714. #elif !defined __CELLOS_LV2__
  715. glUniform4fv(uni.frag, v.Count(), &v[0][0]);
  716. #else
  717. if (uni.frag)
  718. cgGLSetParameterArray4f((CGparameter)uni.frag,
  719. 0, v.Count(), &v[0][0]);
  720. if (uni.vert)
  721. cgGLSetParameterArray4f((CGparameter)uni.vert,
  722. 0, v.Count(), &v[0][0]);
  723. #endif
  724. }
  725. void Shader::Bind() const
  726. {
  727. #if defined USE_D3D9 || defined _XBOX
  728. HRESULT hr;
  729. hr = data->m_dev->SetVertexShader(data->vert_shader);
  730. hr = data->m_dev->SetPixelShader(data->frag_shader);
  731. #elif !defined __CELLOS_LV2__
  732. glUseProgram(data->prog_id);
  733. #else
  734. cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
  735. cgGLBindProgram(data->vert_id);
  736. cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
  737. cgGLBindProgram(data->frag_id);
  738. #endif
  739. }
  740. void Shader::Unbind() const
  741. {
  742. #if defined USE_D3D9 || defined _XBOX
  743. HRESULT hr;
  744. hr = data->m_dev->SetVertexShader(nullptr);
  745. hr = data->m_dev->SetPixelShader(nullptr);
  746. #elif !defined __CELLOS_LV2__
  747. /* FIXME: untested */
  748. glUseProgram(0);
  749. #else
  750. /* FIXME: untested */
  751. cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
  752. cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
  753. #endif
  754. }
  755. Shader::~Shader()
  756. {
  757. #if defined USE_D3D9 || defined _XBOX
  758. data->vert_shader->Release();
  759. data->vert_table->Release();
  760. data->frag_shader->Release();
  761. data->frag_table->Release();
  762. #elif !defined __CELLOS_LV2__
  763. glDetachShader(data->prog_id, data->vert_id);
  764. glDetachShader(data->prog_id, data->frag_id);
  765. glDeleteShader(data->vert_id);
  766. glDeleteShader(data->frag_id);
  767. glDeleteProgram(data->prog_id);
  768. #else
  769. cgDestroyProgram(data->vert_id);
  770. cgDestroyProgram(data->frag_id);
  771. #endif
  772. delete data;
  773. }
  774. /* Try to detect shader compiler features */
  775. int ShaderData::GetVersion()
  776. {
  777. static int version = 0;
  778. #if !defined USE_D3D9 && !defined _XBOX && !defined __CELLOS_LV2__
  779. if (!version)
  780. {
  781. #if defined HAVE_GLES_2X
  782. /* GLES 2.x supports #version 100, that's all. */
  783. return 100;
  784. #else
  785. char buf[4096];
  786. GLsizei len;
  787. int id = glCreateShader(GL_VERTEX_SHADER);
  788. /* Can we compile 1.30 shaders? */
  789. char const *test130 =
  790. "#version 130\n"
  791. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  792. glShaderSource(id, 1, &test130, nullptr);
  793. glCompileShader(id);
  794. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  795. if (len <= 0)
  796. version = 130;
  797. /* If not, can we compile 1.20 shaders? */
  798. if (!version)
  799. {
  800. char const *test120 =
  801. "#version 120\n"
  802. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  803. glShaderSource(id, 1, &test120, nullptr);
  804. glCompileShader(id);
  805. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  806. if (len <= 0)
  807. version = 120;
  808. }
  809. /* Otherwise, assume we can compile 1.10 shaders. */
  810. if (!version)
  811. version = 110;
  812. glDeleteShader(id);
  813. #endif
  814. }
  815. #endif
  816. return version;
  817. }
  818. /*
  819. * Simple shader source patching for old GLSL versions.
  820. */
  821. String ShaderData::Patch(String const &code, ShaderType type)
  822. {
  823. int ver_driver = GetVersion();
  824. String patched_code = code;
  825. if (ver_driver >= 130)
  826. return patched_code;
  827. int ver_shader = 110;
  828. char *parser = strstr(patched_code.C(), "#version");
  829. if (parser)
  830. ver_shader = atoi(parser + strlen("#version"));
  831. /* This is GL ES, we only know version 100. */
  832. if (ver_shader > 100 && ver_driver == 100)
  833. {
  834. /* FIXME: this isn't elegant but honestly, we don't care, this
  835. * whole file is going to die soon. */
  836. char *p = strstr(patched_code.C(), "#version");
  837. if (p)
  838. {
  839. p += 8;
  840. while (*p == ' ')
  841. p++;
  842. if (p[0] == '1' && p[1] && p[2])
  843. p[1] = p[2] = '0';
  844. }
  845. }
  846. if (ver_shader > 120 && ver_driver <= 120)
  847. {
  848. char const *end = patched_code.C() + patched_code.Count() + 1;
  849. /* Find main() */
  850. parser = strstr(patched_code.C(), "main");
  851. if (!parser) return patched_code;
  852. parser = strstr(parser, "(");
  853. if (!parser) return patched_code;
  854. parser = strstr(parser, ")");
  855. if (!parser) return patched_code;
  856. parser = strstr(parser, "{");
  857. if (!parser) return patched_code;
  858. char *main = parser + 1;
  859. /* Perform main() replaces */
  860. char const * const main_replaces[] =
  861. {
  862. #if 0
  863. "in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;",
  864. "in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;",
  865. "in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;",
  866. "in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;",
  867. "in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;",
  868. "in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;",
  869. "in vec2 in_MultiTexCoord0;",
  870. "vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;",
  871. "in vec2 in_MultiTexCoord1;",
  872. "vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;",
  873. "in vec2 in_MultiTexCoord2;",
  874. "vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;",
  875. "in vec2 in_MultiTexCoord3;",
  876. "vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;",
  877. "in vec2 in_MultiTexCoord4;",
  878. "vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;",
  879. "in vec2 in_MultiTexCoord5;",
  880. "vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;",
  881. "in vec2 in_MultiTexCoord6;",
  882. "vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;",
  883. "in vec2 in_MultiTexCoord7;",
  884. "vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;",
  885. #endif
  886. nullptr
  887. };
  888. for (char const * const *rep = main_replaces; rep[0]; rep += 2)
  889. {
  890. char *match = strstr(patched_code.C(), rep[0]);
  891. if (match && match < main)
  892. {
  893. size_t l0 = strlen(rep[0]);
  894. size_t l1 = strlen(rep[1]);
  895. memmove(main + l1, main, end - main);
  896. memcpy(main, rep[1], l1);
  897. memset(match, ' ', l0);
  898. main += l1;
  899. end += l1;
  900. }
  901. }
  902. /* Perform small replaces */
  903. char const * const fast_replaces[] =
  904. {
  905. "#version 130", "#version 120",
  906. "in vec2", type == ShaderType::Vertex ? "attribute vec2" : "varying vec2",
  907. "in vec3", type == ShaderType::Vertex ? "attribute vec3" : "varying vec3",
  908. "in vec4", type == ShaderType::Vertex ? "attribute vec4" : "varying vec4",
  909. "in mat4", type == ShaderType::Vertex ? "attribute mat4" : "varying mat4",
  910. "out vec2", "varying vec2",
  911. "out vec3", "varying vec3",
  912. "out vec4", "varying vec4",
  913. "out mat4", "varying mat4",
  914. nullptr
  915. };
  916. for (char const * const *rep = fast_replaces; rep[0]; rep += 2)
  917. {
  918. char *match;
  919. while ((match = strstr(patched_code.C(), rep[0])))
  920. {
  921. size_t l0 = strlen(rep[0]);
  922. size_t l1 = strlen(rep[1]);
  923. if (l1 > l0)
  924. memmove(match + l1, match + l0, (end - match) - l0);
  925. memcpy(match, rep[1], l1);
  926. if (l1 < l0)
  927. memset(match + l0, ' ', l1 - l0);
  928. end += l1 - l0;
  929. }
  930. }
  931. }
  932. patched_code.Resize(strlen(patched_code.C()));
  933. return patched_code;
  934. }
  935. } /* namespace lol */