991 行
30 KiB

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