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