981 linhas
29 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. GLint max_len;
  322. glGetProgramiv(data->prog_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
  323. char* name_buffer = new char[max_len];
  324. for (int i = 0; i < num_attribs; ++i)
  325. {
  326. int attrib_len;
  327. int attrib_size;
  328. int attrib_type;
  329. glGetActiveAttrib(data->prog_id, i, max_len, &attrib_len, (GLint*)&attrib_size, (GLenum*)&attrib_type, name_buffer);
  330. String name(name_buffer);
  331. int index = 0;
  332. VertexUsage usage = VertexUsage::Max;
  333. for (int j = 0; j < VertexUsage::Max; ++j)
  334. {
  335. if (name.StartsWith(attribute_names[j]))
  336. {
  337. usage = VertexUsage(j);
  338. char* idx_ptr = name.C() + strlen(attribute_names[j]);
  339. index = strtol(idx_ptr, nullptr, 10);
  340. break;
  341. }
  342. }
  343. if (usage == VertexUsage::Max || index == LONG_MIN || index == LONG_MAX)
  344. {
  345. Log::Error("unable to parse attribute sementic from name: %s", name_buffer);
  346. }
  347. else
  348. {
  349. GLint location = glGetAttribLocation(data->prog_id, name_buffer);
  350. uint64_t flags = (uint64_t)(uint16_t)usage << 16;
  351. flags |= (uint64_t)(uint16_t)index;
  352. // TODO: this is here just in case. Remove this once everything has been correctly tested
  353. #ifdef _DEBUG
  354. if (data->attrib_locations.HasKey(flags))
  355. {
  356. Log::Error("an error occured while parsing attribute sementics");
  357. }
  358. #endif
  359. data->attrib_locations[flags] = location;
  360. }
  361. }
  362. delete[] name_buffer;
  363. #endif
  364. }
  365. int Shader::GetAttribCount() const
  366. {
  367. return data->attrib_locations.Count();
  368. }
  369. ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const
  370. {
  371. ShaderAttrib ret;
  372. ret.m_flags = (uint64_t)(uint16_t)usage << 16;
  373. ret.m_flags |= (uint64_t)(uint16_t)index;
  374. #if defined USE_D3D9 || defined _XBOX
  375. #elif !defined __CELLOS_LV2__
  376. GLint l;
  377. if (!data->attrib_locations.TryGetValue(ret.m_flags, l))
  378. {
  379. Log::Error("queried attribute is unavailable for this shader");
  380. }
  381. ret.m_flags |= (uint64_t)(uint32_t)l << 32;
  382. #else
  383. /* FIXME: can we do this at all on the PS3? */
  384. #endif
  385. return ret;
  386. }
  387. ShaderUniform Shader::GetUniformLocation(char const *uni) const
  388. {
  389. ShaderUniform ret;
  390. #if defined USE_D3D9 || defined _XBOX
  391. /* Global variables are prefixed with "$" */
  392. String tmpname = String("$") + uni;
  393. D3DXCONSTANT_DESC cdesc;
  394. D3DXHANDLE hr;
  395. UINT count;
  396. count = 0;
  397. hr = data->frag_table->GetConstantByName(nullptr, tmpname.C());
  398. if (hr)
  399. data->frag_table->GetConstantDesc(hr, &cdesc, &count);
  400. if (count)
  401. {
  402. ret.frag = cdesc.RegisterIndex;
  403. ret.flags |= 1;
  404. }
  405. count = 0;
  406. hr = data->vert_table->GetConstantByName(nullptr, tmpname.C());
  407. if (hr)
  408. data->vert_table->GetConstantDesc(hr, &cdesc, &count);
  409. if (count)
  410. {
  411. ret.vert = cdesc.RegisterIndex;
  412. ret.flags |= 2;
  413. }
  414. #elif !defined __CELLOS_LV2__
  415. ret.frag = (uintptr_t)glGetUniformLocation(data->prog_id, uni);
  416. ret.vert = 0;
  417. #else
  418. ret.frag = (uintptr_t)cgGetNamedParameter(data->frag_id, uni);
  419. ret.vert = (uintptr_t)cgGetNamedParameter(data->vert_id, uni);
  420. #endif
  421. return ret;
  422. }
  423. /*
  424. * Uniform setters for scalars
  425. */
  426. void Shader::SetUniform(ShaderUniform const &uni, int i)
  427. {
  428. #if defined USE_D3D9 || defined _XBOX
  429. SetUniform(uni, ivec4(i, 0, 0, 0));
  430. #elif !defined __CELLOS_LV2__
  431. glUniform1i(uni.frag, i);
  432. #else
  433. /* FIXME: does this exist at all? cgGLSetParameter1i doesn't. */
  434. #endif
  435. }
  436. void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v)
  437. {
  438. #if defined USE_D3D9 || defined _XBOX
  439. SetUniform(uni, ivec4(v, 0, 0));
  440. #elif !defined __CELLOS_LV2__
  441. glUniform2i(uni.frag, v.x, v.y);
  442. #else
  443. /* FIXME: does this exist at all? */
  444. #endif
  445. }
  446. void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v)
  447. {
  448. #if defined USE_D3D9 || defined _XBOX
  449. SetUniform(uni, ivec4(v, 0));
  450. #elif !defined __CELLOS_LV2__
  451. glUniform3i(uni.frag, v.x, v.y, v.z);
  452. #else
  453. /* FIXME: does this exist at all? */
  454. #endif
  455. }
  456. void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v)
  457. {
  458. #if defined USE_D3D9 || defined _XBOX
  459. if (uni.flags & 1)
  460. data->m_dev->SetPixelShaderConstantI((UINT)uni.frag, &v[0], 1);
  461. if (uni.flags & 2)
  462. data->m_dev->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1);
  463. #elif !defined __CELLOS_LV2__
  464. glUniform4i(uni.frag, v.x, v.y, v.z, v.w);
  465. #else
  466. /* FIXME: does this exist at all? */
  467. #endif
  468. }
  469. void Shader::SetUniform(ShaderUniform const &uni, float f)
  470. {
  471. #if defined USE_D3D9 || defined _XBOX
  472. SetUniform(uni, vec4(f, 0, 0, 0));
  473. #elif !defined __CELLOS_LV2__
  474. glUniform1f(uni.frag, f);
  475. #else
  476. if (uni.frag)
  477. cgGLSetParameter1f((CGparameter)uni.frag, f);
  478. if (uni.vert)
  479. cgGLSetParameter1f((CGparameter)uni.vert, f);
  480. #endif
  481. }
  482. void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v)
  483. {
  484. #if defined USE_D3D9 || defined _XBOX
  485. SetUniform(uni, vec4(v, 0, 0));
  486. #elif !defined __CELLOS_LV2__
  487. glUniform2fv(uni.frag, 1, &v[0]);
  488. #else
  489. if (uni.frag)
  490. cgGLSetParameter2fv((CGparameter)uni.frag, &v[0]);
  491. if (uni.vert)
  492. cgGLSetParameter2fv((CGparameter)uni.vert, &v[0]);
  493. #endif
  494. }
  495. void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v)
  496. {
  497. #if defined USE_D3D9 || defined _XBOX
  498. SetUniform(uni, vec4(v, 0));
  499. #elif !defined __CELLOS_LV2__
  500. glUniform3fv(uni.frag, 1, &v[0]);
  501. #else
  502. if (uni.frag)
  503. cgGLSetParameter3fv((CGparameter)uni.frag, &v[0]);
  504. if (uni.vert)
  505. cgGLSetParameter3fv((CGparameter)uni.vert, &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. #elif !defined __CELLOS_LV2__
  516. glUniform4fv(uni.frag, 1, &v[0]);
  517. #else
  518. if (uni.frag)
  519. cgGLSetParameter4fv((CGparameter)uni.frag, &v[0]);
  520. if (uni.vert)
  521. cgGLSetParameter4fv((CGparameter)uni.vert, &v[0]);
  522. #endif
  523. }
  524. void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m)
  525. {
  526. #if defined USE_D3D9 || defined _XBOX
  527. /* FIXME: do we need padding here like for the mat3 version? */
  528. if (uni.flags & 1)
  529. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 1);
  530. if (uni.flags & 2)
  531. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1);
  532. #elif !defined __CELLOS_LV2__
  533. glUniformMatrix2fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  534. #else
  535. mat4 tmp(m, 1.0f, 1.0f);
  536. if (uni.frag)
  537. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  538. if (uni.vert)
  539. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  540. #endif
  541. }
  542. void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m)
  543. {
  544. #if defined USE_D3D9 || defined _XBOX
  545. /* Padding matrix columns is necessary on DirectX. We need to create
  546. * a new data structure; a 4×4 matrix will do. */
  547. mat4 tmp(m, 1.0f);
  548. if (uni.flags & 1)
  549. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &tmp[0][0], 3);
  550. if (uni.flags & 2)
  551. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3);
  552. #elif !defined __CELLOS_LV2__
  553. glUniformMatrix3fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  554. #else
  555. /* FIXME: check it's the proper way to do this */
  556. mat4 tmp(m, 1.0f);
  557. if (uni.frag)
  558. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  559. if (uni.vert)
  560. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  561. #endif
  562. }
  563. void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
  564. {
  565. #if defined USE_D3D9 || defined _XBOX
  566. if (uni.flags & 1)
  567. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 4);
  568. if (uni.flags & 2)
  569. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4);
  570. #elif !defined __CELLOS_LV2__
  571. glUniformMatrix4fv(uni.frag, 1, GL_FALSE, &m[0][0]);
  572. #else
  573. if (uni.frag)
  574. cgGLSetMatrixParameterfc((CGparameter)uni.frag, &m[0][0]);
  575. if (uni.vert)
  576. cgGLSetMatrixParameterfc((CGparameter)uni.vert, &m[0][0]);
  577. #endif
  578. }
  579. void Shader::SetUniform(ShaderUniform const &uni, ShaderTexture tex, int index)
  580. {
  581. #if defined USE_D3D9 || defined _XBOX
  582. data->m_dev->SetTexture(index, (LPDIRECT3DTEXTURE9)tex.m_flags);
  583. data->m_dev->SetSamplerState(index, D3DSAMP_MAGFILTER, tex.m_attrib & 0xff);
  584. data->m_dev->SetSamplerState(index, D3DSAMP_MINFILTER, (tex.m_attrib >> 8) & 0xff);
  585. data->m_dev->SetSamplerState(index, D3DSAMP_MIPFILTER, (tex.m_attrib >> 16) & 0xff);
  586. #elif !defined __CELLOS_LV2__
  587. glActiveTexture(GL_TEXTURE0 + index);
  588. //glEnable(GL_TEXTURE_2D);
  589. glBindTexture(GL_TEXTURE_2D, (int)tex.m_flags);
  590. SetUniform(uni, index);
  591. #else
  592. /* FIXME: unimplemented */
  593. #endif
  594. }
  595. /*
  596. * Uniform setters for arrays
  597. */
  598. void Shader::SetUniform(ShaderUniform const &uni, Array<float> const &v)
  599. {
  600. #if defined USE_D3D9 || defined _XBOX
  601. /* FIXME: this will not work properly because we don't know how tell DX9
  602. * it's a bunch of floats instead of vec4. */
  603. if (uni.flags & 1)
  604. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  605. &v[0], v.Count() / 4);
  606. if (uni.flags & 2)
  607. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  608. &v[0], v.Count() / 4);
  609. #elif !defined __CELLOS_LV2__
  610. glUniform1fv(uni.frag, v.Count(), &v[0]);
  611. #else
  612. if (uni.frag)
  613. cgGLSetParameterArray1f((CGparameter)uni.frag,
  614. 0, v.Count(), &v[0]);
  615. if (uni.vert)
  616. cgGLSetParameterArray1f((CGparameter)uni.vert,
  617. 0, v.Count(), &v[0]);
  618. #endif
  619. }
  620. void Shader::SetUniform(ShaderUniform const &uni, Array<vec2> const &v)
  621. {
  622. #if defined USE_D3D9 || defined _XBOX
  623. /* FIXME: this will not work properly because we don't know how tell DX9
  624. * it's a bunch of vec2 instead of vec4. */
  625. if (uni.flags & 1)
  626. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  627. &v[0][0], v.Count() / 2);
  628. if (uni.flags & 2)
  629. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  630. &v[0][0], v.Count() / 2);
  631. #elif !defined __CELLOS_LV2__
  632. glUniform2fv(uni.frag, v.Count(), &v[0][0]);
  633. #else
  634. if (uni.frag)
  635. cgGLSetParameterArray2f((CGparameter)uni.frag,
  636. 0, v.Count(), &v[0][0]);
  637. if (uni.vert)
  638. cgGLSetParameterArray2f((CGparameter)uni.vert,
  639. 0, v.Count(), &v[0][0]);
  640. #endif
  641. }
  642. void Shader::SetUniform(ShaderUniform const &uni, Array<vec3> const &v)
  643. {
  644. #if defined USE_D3D9 || defined _XBOX
  645. /* FIXME: this will not work properly because we don't know how tell DX9
  646. * it's a bunch of vec3 instead of vec4. */
  647. if (uni.flags & 1)
  648. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  649. &v[0][0], v.Count());
  650. if (uni.flags & 2)
  651. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  652. &v[0][0], v.Count());
  653. #elif !defined __CELLOS_LV2__
  654. glUniform3fv(uni.frag, v.Count(), &v[0][0]);
  655. #else
  656. if (uni.frag)
  657. cgGLSetParameterArray3f((CGparameter)uni.frag,
  658. 0, v.Count(), &v[0][0]);
  659. if (uni.vert)
  660. cgGLSetParameterArray3f((CGparameter)uni.vert,
  661. 0, v.Count(), &v[0][0]);
  662. #endif
  663. }
  664. void Shader::SetUniform(ShaderUniform const &uni, Array<vec4> const &v)
  665. {
  666. #if defined USE_D3D9 || defined _XBOX
  667. if (uni.flags & 1)
  668. data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
  669. &v[0][0], v.Count());
  670. if (uni.flags & 2)
  671. data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
  672. &v[0][0], v.Count());
  673. #elif !defined __CELLOS_LV2__
  674. glUniform4fv(uni.frag, v.Count(), &v[0][0]);
  675. #else
  676. if (uni.frag)
  677. cgGLSetParameterArray4f((CGparameter)uni.frag,
  678. 0, v.Count(), &v[0][0]);
  679. if (uni.vert)
  680. cgGLSetParameterArray4f((CGparameter)uni.vert,
  681. 0, v.Count(), &v[0][0]);
  682. #endif
  683. }
  684. void Shader::Bind() const
  685. {
  686. #if defined USE_D3D9 || defined _XBOX
  687. HRESULT hr;
  688. hr = data->m_dev->SetVertexShader(data->vert_shader);
  689. hr = data->m_dev->SetPixelShader(data->frag_shader);
  690. #elif !defined __CELLOS_LV2__
  691. glUseProgram(data->prog_id);
  692. #else
  693. cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
  694. cgGLBindProgram(data->vert_id);
  695. cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
  696. cgGLBindProgram(data->frag_id);
  697. #endif
  698. }
  699. void Shader::Unbind() const
  700. {
  701. #if defined USE_D3D9 || defined _XBOX
  702. HRESULT hr;
  703. hr = data->m_dev->SetVertexShader(nullptr);
  704. hr = data->m_dev->SetPixelShader(nullptr);
  705. #elif !defined __CELLOS_LV2__
  706. /* FIXME: untested */
  707. glUseProgram(0);
  708. #else
  709. /* FIXME: untested */
  710. cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
  711. cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
  712. #endif
  713. }
  714. Shader::~Shader()
  715. {
  716. #if defined USE_D3D9 || defined _XBOX
  717. data->vert_shader->Release();
  718. data->vert_table->Release();
  719. data->frag_shader->Release();
  720. data->frag_table->Release();
  721. #elif !defined __CELLOS_LV2__
  722. glDetachShader(data->prog_id, data->vert_id);
  723. glDetachShader(data->prog_id, data->frag_id);
  724. glDeleteShader(data->vert_id);
  725. glDeleteShader(data->frag_id);
  726. glDeleteProgram(data->prog_id);
  727. #else
  728. cgDestroyProgram(data->vert_id);
  729. cgDestroyProgram(data->frag_id);
  730. #endif
  731. delete data;
  732. }
  733. /* Try to detect shader compiler features */
  734. int ShaderData::GetVersion()
  735. {
  736. static int version = 0;
  737. #if !defined USE_D3D9 && !defined _XBOX && !defined __CELLOS_LV2__
  738. if (!version)
  739. {
  740. #if defined HAVE_GLES_2X
  741. /* GLES 2.x supports #version 100, that's all. */
  742. return 100;
  743. #else
  744. char buf[4096];
  745. GLsizei len;
  746. int id = glCreateShader(GL_VERTEX_SHADER);
  747. /* Can we compile 1.30 shaders? */
  748. char const *test130 =
  749. "#version 130\n"
  750. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  751. glShaderSource(id, 1, &test130, nullptr);
  752. glCompileShader(id);
  753. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  754. if (len <= 0)
  755. version = 130;
  756. /* If not, can we compile 1.20 shaders? */
  757. if (!version)
  758. {
  759. char const *test120 =
  760. "#version 120\n"
  761. "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
  762. glShaderSource(id, 1, &test120, nullptr);
  763. glCompileShader(id);
  764. glGetShaderInfoLog(id, sizeof(buf), &len, buf);
  765. if (len <= 0)
  766. version = 120;
  767. }
  768. /* Otherwise, assume we can compile 1.10 shaders. */
  769. if (!version)
  770. version = 110;
  771. glDeleteShader(id);
  772. #endif
  773. }
  774. #endif
  775. return version;
  776. }
  777. /* Simple shader source patching for old GLSL versions.
  778. */
  779. void ShaderData::Patch(char *dst, char const *vert, char const *frag)
  780. {
  781. int ver_driver = GetVersion();
  782. strcpy(dst, vert ? vert : frag);
  783. if (ver_driver >= 130)
  784. return;
  785. int ver_shader = 110;
  786. char *parser = strstr(dst, "#version");
  787. if (parser)
  788. ver_shader = atoi(parser + strlen("#version"));
  789. /* This is GL ES, we only know version 100. */
  790. if (ver_shader > 100 && ver_driver == 100)
  791. {
  792. /* FIXME: this isn't elegant but honestly, we don't care, this
  793. * whole file is going to die soon. */
  794. char *p = strstr(dst, "#version");
  795. if (p)
  796. {
  797. p += 8;
  798. while (*p == ' ')
  799. p++;
  800. if (p[0] == '1' && p[1] && p[2])
  801. p[1] = p[2] = '0';
  802. }
  803. }
  804. if (ver_shader > 120 && ver_driver <= 120)
  805. {
  806. char const *end = dst + strlen(dst) + 1;
  807. /* Find main() */
  808. parser = strstr(dst, "main");
  809. if (!parser) return;
  810. parser = strstr(parser, "(");
  811. if (!parser) return;
  812. parser = strstr(parser, ")");
  813. if (!parser) return;
  814. parser = strstr(parser, "{");
  815. if (!parser) return;
  816. char *main = parser + 1;
  817. /* Perform main() replaces */
  818. char const * const main_replaces[] =
  819. {
  820. #if 0
  821. "in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;",
  822. "in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;",
  823. "in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;",
  824. "in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;",
  825. "in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;",
  826. "in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;",
  827. "in vec2 in_MultiTexCoord0;",
  828. "vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;",
  829. "in vec2 in_MultiTexCoord1;",
  830. "vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;",
  831. "in vec2 in_MultiTexCoord2;",
  832. "vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;",
  833. "in vec2 in_MultiTexCoord3;",
  834. "vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;",
  835. "in vec2 in_MultiTexCoord4;",
  836. "vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;",
  837. "in vec2 in_MultiTexCoord5;",
  838. "vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;",
  839. "in vec2 in_MultiTexCoord6;",
  840. "vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;",
  841. "in vec2 in_MultiTexCoord7;",
  842. "vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;",
  843. #endif
  844. nullptr
  845. };
  846. for (char const * const *rep = main_replaces; rep[0]; rep += 2)
  847. {
  848. char *match = strstr(dst, rep[0]);
  849. if (match && match < main)
  850. {
  851. size_t l0 = strlen(rep[0]);
  852. size_t l1 = strlen(rep[1]);
  853. memmove(main + l1, main, end - main);
  854. memcpy(main, rep[1], l1);
  855. memset(match, ' ', l0);
  856. main += l1;
  857. end += l1;
  858. }
  859. }
  860. /* Perform small replaces */
  861. char const * const fast_replaces[] =
  862. {
  863. "#version 130", "#version 120",
  864. "in vec2", vert ? "attribute vec2" : "varying vec2",
  865. "in vec3", vert ? "attribute vec3" : "varying vec3",
  866. "in vec4", vert ? "attribute vec4" : "varying vec4",
  867. "in mat4", vert ? "attribute mat4" : "varying mat4",
  868. "out vec2", "varying vec2",
  869. "out vec3", "varying vec3",
  870. "out vec4", "varying vec4",
  871. "out mat4", "varying mat4",
  872. nullptr
  873. };
  874. for (char const * const *rep = fast_replaces; rep[0]; rep += 2)
  875. {
  876. char *match;
  877. while ((match = strstr(dst, rep[0])))
  878. {
  879. size_t l0 = strlen(rep[0]);
  880. size_t l1 = strlen(rep[1]);
  881. if (l1 > l0)
  882. memmove(match + l1, match + l0, (end - match) - l0);
  883. memcpy(match, rep[1], l1);
  884. if (l1 < l0)
  885. memset(match + l0, ' ', l1 - l0);
  886. end += l1 - l0;
  887. }
  888. }
  889. }
  890. }
  891. } /* namespace lol */