25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1029 lines
31 KiB

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