shaderc.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /*
  2. * Copyright 2011-2012 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include <stdio.h>
  6. #include <stdint.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <string>
  10. #include <vector>
  11. #include "glsl_optimizer.h"
  12. #define MAX_TAGS 256
  13. extern "C" {
  14. # include <fpp.h>
  15. } // extern "C"
  16. #if 0
  17. # define BX_TRACE(_format, ...) fprintf(stderr, "" _format "\n", ##__VA_ARGS__)
  18. #endif // DEBUG
  19. #define BX_NAMESPACE 1
  20. #include <bx/bx.h>
  21. #if BX_PLATFORM_LINUX
  22. # define _stricmp strcasecmp
  23. #endif // BX_PLATFORM_LINUX
  24. #include <bx/commandline.h>
  25. #include <bx/countof.h>
  26. #include <bx/endian.h>
  27. #include <bx/uint32_t.h>
  28. #if BX_PLATFORM_WINDOWS
  29. # include <d3dx9.h>
  30. #endif // BX_PLATFORM_WINDOWS
  31. long int fsize(FILE* _file)
  32. {
  33. long int pos = ftell(_file);
  34. fseek(_file, 0L, SEEK_END);
  35. long int size = ftell(_file);
  36. fseek(_file, pos, SEEK_SET);
  37. return size;
  38. }
  39. struct ConstantType
  40. {
  41. enum Enum
  42. {
  43. Uniform1i,
  44. Uniform1f,
  45. End,
  46. Uniform1iv,
  47. Uniform1fv,
  48. Uniform2fv,
  49. Uniform3fv,
  50. Uniform4fv,
  51. Uniform3x3fv,
  52. Uniform4x4fv,
  53. Count,
  54. TypeMask = 0x7f,
  55. FragmentBit = 0x80
  56. };
  57. };
  58. static const char* s_constantTypeName[ConstantType::Count] =
  59. {
  60. "int",
  61. "float",
  62. NULL,
  63. "int",
  64. "float",
  65. "float2",
  66. "float3",
  67. "float4",
  68. "float3x3",
  69. "float4x4",
  70. };
  71. struct Uniform
  72. {
  73. std::string name;
  74. ConstantType::Enum type;
  75. uint8_t num;
  76. uint16_t regIndex;
  77. uint16_t regCount;
  78. };
  79. typedef std::vector<Uniform> UniformArray;
  80. #if BX_PLATFORM_WINDOWS
  81. struct ConstRemap
  82. {
  83. ConstantType::Enum id;
  84. D3DXPARAMETER_CLASS paramClass;
  85. D3DXPARAMETER_TYPE paramType;
  86. uint32_t paramBytes;
  87. };
  88. static const ConstRemap s_constRemap[7] =
  89. {
  90. { ConstantType::Uniform1iv, D3DXPC_SCALAR, D3DXPT_INT, 4 },
  91. { ConstantType::Uniform1fv, D3DXPC_SCALAR, D3DXPT_FLOAT, 4 },
  92. { ConstantType::Uniform2fv, D3DXPC_VECTOR, D3DXPT_FLOAT, 8 },
  93. { ConstantType::Uniform3fv, D3DXPC_VECTOR, D3DXPT_FLOAT, 12 },
  94. { ConstantType::Uniform4fv, D3DXPC_VECTOR, D3DXPT_FLOAT, 16 },
  95. { ConstantType::Uniform3x3fv, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 36 },
  96. { ConstantType::Uniform4x4fv, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 64 },
  97. };
  98. ConstantType::Enum findConstantType(const D3DXCONSTANT_DESC& constDesc)
  99. {
  100. uint32_t count = sizeof(s_constRemap)/sizeof(ConstRemap);
  101. for (uint32_t ii = 0; ii < count; ++ii)
  102. {
  103. const ConstRemap& remap = s_constRemap[ii];
  104. if (remap.paramClass == constDesc.Class
  105. && remap.paramType == constDesc.Type
  106. && (constDesc.Bytes%remap.paramBytes) == 0)
  107. {
  108. return remap.id;
  109. }
  110. }
  111. return ConstantType::Count;
  112. }
  113. static uint32_t s_optimizationLevel[4] =
  114. {
  115. D3DXSHADER_OPTIMIZATION_LEVEL0,
  116. D3DXSHADER_OPTIMIZATION_LEVEL1,
  117. D3DXSHADER_OPTIMIZATION_LEVEL2,
  118. D3DXSHADER_OPTIMIZATION_LEVEL3,
  119. };
  120. #endif // BX_PLATFORM_WINDOWS
  121. class Stream
  122. {
  123. public:
  124. Stream(FILE* _file, bool _bigEndian = false)
  125. : m_file(_file)
  126. , m_bigEndian(_bigEndian)
  127. {
  128. }
  129. ~Stream()
  130. {
  131. }
  132. void close()
  133. {
  134. m_file = NULL;
  135. }
  136. void writef(const char* _format, ...)
  137. {
  138. if (NULL != m_file)
  139. {
  140. va_list argList;
  141. va_start(argList, _format);
  142. char temp[2048];
  143. int len = vsnprintf(temp, sizeof(temp), _format, argList);
  144. fwrite(temp, len, 1, m_file);
  145. va_end(argList);
  146. }
  147. }
  148. void write(const char* _str)
  149. {
  150. if (NULL != m_file)
  151. {
  152. fwrite(_str, strlen(_str), 1, m_file);
  153. }
  154. }
  155. void write(const void* _data, size_t _size)
  156. {
  157. if (NULL != m_file)
  158. {
  159. fwrite(_data, _size, 1, m_file);
  160. }
  161. }
  162. template<typename Ty>
  163. void write(Ty _value)
  164. {
  165. Ty temp = m_bigEndian ? bx::bigEndian<Ty>(_value) : _value;
  166. write(&temp, sizeof(Ty) );
  167. }
  168. private:
  169. FILE* m_file;
  170. bool m_bigEndian;
  171. };
  172. class LineReader
  173. {
  174. public:
  175. LineReader(const char* _str)
  176. : m_str(_str)
  177. , m_pos(0)
  178. , m_size( (uint32_t)strlen(_str) )
  179. {
  180. }
  181. std::string getLine()
  182. {
  183. const char* str = &m_str[m_pos];
  184. skipLine();
  185. const char* eol = &m_str[m_pos];
  186. std::string tmp;
  187. tmp.assign(str, eol-str);
  188. return tmp;
  189. }
  190. bool isEof() const
  191. {
  192. return m_str[m_pos] == '\0';
  193. }
  194. private:
  195. void skipLine()
  196. {
  197. const char* str = &m_str[m_pos];
  198. const char* eol = strstr(str, "\n\r");
  199. if (NULL != eol)
  200. {
  201. m_pos += eol-str+2;
  202. return;
  203. }
  204. eol = strstr(str, "\n");
  205. if (NULL != eol)
  206. {
  207. m_pos += eol-str+1;
  208. return;
  209. }
  210. m_pos += (uint32_t)strlen(str);
  211. }
  212. const char* m_str;
  213. uint32_t m_pos;
  214. uint32_t m_size;
  215. };
  216. void printCode(const char* _code)
  217. {
  218. fprintf(stderr, "Code:\n---\n");
  219. LineReader lr(_code);
  220. for (uint32_t line = 1; !lr.isEof(); ++line)
  221. {
  222. fprintf(stderr, "%3d: %s", line, lr.getLine().c_str() );
  223. }
  224. fprintf(stderr, "---\n");
  225. }
  226. bool compileGLSLShader(CommandLine& _cmdLine, const std::string& _code, const char* _outFilePath)
  227. {
  228. const glslopt_shader_type type = tolower(_cmdLine.findOption('\0', "type")[0]) == 'f' ? kGlslOptShaderFragment : kGlslOptShaderVertex;
  229. glslopt_ctx* ctx = glslopt_initialize(false);
  230. glslopt_shader* shader = glslopt_optimize(ctx, type, _code.c_str(), 0);
  231. if( !glslopt_get_status(shader) )
  232. {
  233. printCode(_code.c_str() );
  234. fprintf(stderr, "Error: %s\n", glslopt_get_log(shader) );
  235. glslopt_cleanup(ctx);
  236. return false;
  237. }
  238. const char* optimizedShader = glslopt_get_output(shader);
  239. FILE* out = fopen(_outFilePath, "wb");
  240. if (NULL == out)
  241. {
  242. fprintf(stderr, "Unable to open output file '%s'.", _outFilePath);
  243. glslopt_cleanup(ctx);
  244. return false;
  245. }
  246. Stream stream(out);
  247. const char* profile = _cmdLine.findOption('p');
  248. if (NULL == profile)
  249. {
  250. stream.write("#ifdef GL_ES\n");
  251. stream.write("precision highp float;\n");
  252. stream.write("#endif // GL_ES\n\n");
  253. }
  254. else
  255. {
  256. stream.writef("#version %s\n\n", profile);
  257. }
  258. stream.write(optimizedShader, strlen(optimizedShader) );
  259. uint8_t nul = 0;
  260. stream.write(nul);
  261. stream.close();
  262. fclose(out);
  263. glslopt_cleanup(ctx);
  264. return true;
  265. }
  266. bool compileHLSLShader(CommandLine& _cmdLine, const std::string& _code, const char* _outFilePath)
  267. {
  268. #if BX_PLATFORM_WINDOWS
  269. const char* profile = _cmdLine.findOption('p');
  270. if (NULL == profile)
  271. {
  272. printf("Shader profile must be specified.\n");
  273. return false;
  274. }
  275. bool bigEndian = _cmdLine.hasArg('\0', "xbox360");
  276. uint32_t flags = 0;
  277. flags |= _cmdLine.hasArg('\0', "debug") ? D3DXSHADER_DEBUG : 0;
  278. flags |= _cmdLine.hasArg('\0', "avoid-flow-control") ? D3DXSHADER_AVOID_FLOW_CONTROL : 0;
  279. flags |= _cmdLine.hasArg('\0', "no-preshader") ? D3DXSHADER_NO_PRESHADER : 0;
  280. flags |= _cmdLine.hasArg('\0', "partial-precision") ? D3DXSHADER_PARTIALPRECISION : 0;
  281. flags |= _cmdLine.hasArg('\0', "prefer-flow-control") ? D3DXSHADER_PREFER_FLOW_CONTROL : 0;
  282. flags |= _cmdLine.hasArg('\0', "backwards-compatibility") ? D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY : 0;
  283. bool werror = _cmdLine.hasArg('\0', "Werror");
  284. uint32_t optimization = 3;
  285. if (_cmdLine.hasArg(optimization, 'O') )
  286. {
  287. optimization = bx::uint32_min(optimization, countof(s_optimizationLevel)-1);
  288. flags |= s_optimizationLevel[optimization];
  289. }
  290. else
  291. {
  292. flags |= D3DXSHADER_SKIPOPTIMIZATION;
  293. }
  294. BX_TRACE("Profile: %s", profile);
  295. BX_TRACE("Flags: 0x%08x", flags);
  296. BX_TRACE("Big Endian: %s", bigEndian?"true":"false");
  297. LPD3DXBUFFER code;
  298. LPD3DXBUFFER errorMsg;
  299. LPD3DXCONSTANTTABLE constantTable;
  300. HRESULT hr = D3DXCompileShader(_code.c_str()
  301. , _code.size()
  302. , NULL
  303. , NULL
  304. , "main"
  305. , profile
  306. , flags
  307. , &code
  308. , &errorMsg
  309. , &constantTable
  310. );
  311. if (FAILED(hr)
  312. || werror && NULL != errorMsg)
  313. {
  314. printCode(_code.c_str() );
  315. fprintf(stderr, "Error: 0x%08x %s\n", hr, errorMsg->GetBufferPointer() );
  316. return false;
  317. }
  318. D3DXCONSTANTTABLE_DESC desc;
  319. hr = constantTable->GetDesc(&desc);
  320. if (FAILED(hr) )
  321. {
  322. fprintf(stderr, "Error 0x%08x\n", hr);
  323. return false;
  324. }
  325. BX_TRACE("Creator: %s 0x%08x", desc.Creator, desc.Version);
  326. BX_TRACE("Num constants: %d", desc.Constants);
  327. BX_TRACE("# cl ty RxC S By Name");
  328. UniformArray uniforms;
  329. for (uint32_t ii = 0; ii < desc.Constants; ++ii)
  330. {
  331. D3DXHANDLE handle = constantTable->GetConstant(NULL, ii);
  332. D3DXCONSTANT_DESC constDesc;
  333. uint32_t count;
  334. constantTable->GetConstantDesc(handle, &constDesc, &count);
  335. BX_TRACE("%3d %2d %2d [%dx%d] %d %3d %s[%d] c%d (%d)"
  336. , ii
  337. , constDesc.Class
  338. , constDesc.Type
  339. , constDesc.Rows
  340. , constDesc.Columns
  341. , constDesc.StructMembers
  342. , constDesc.Bytes
  343. , constDesc.Name
  344. , constDesc.Elements
  345. , constDesc.RegisterIndex
  346. , constDesc.RegisterCount
  347. );
  348. ConstantType::Enum type = findConstantType(constDesc);
  349. if (ConstantType::Count != type)
  350. {
  351. Uniform un;
  352. un.name = '$' == constDesc.Name[0] ? constDesc.Name+1 : constDesc.Name;
  353. un.type = type;
  354. un.num = constDesc.Elements;
  355. un.regIndex = constDesc.RegisterIndex;
  356. un.regCount = constDesc.RegisterCount;
  357. uniforms.push_back(un);
  358. }
  359. }
  360. FILE* out = fopen(_outFilePath, "wb");
  361. if (NULL == out)
  362. {
  363. fprintf(stderr, "Unable to open output file '%s'.", _outFilePath);
  364. return false;
  365. }
  366. Stream stream(out, bigEndian);
  367. uint16_t count = (uint16_t)uniforms.size();
  368. stream.write(count);
  369. uint32_t fragmentBit = profile[0] == 'p' ? ConstantType::FragmentBit : 0;
  370. for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
  371. {
  372. const Uniform& un = *it;
  373. uint8_t nameSize = (uint8_t)un.name.size();
  374. stream.write(nameSize);
  375. stream.write(un.name.c_str(), nameSize);
  376. stream.write<uint8_t>(un.type|fragmentBit);
  377. stream.write(un.num);
  378. stream.write(un.regIndex);
  379. stream.write(un.regCount);
  380. BX_TRACE("%s, %s, %d, %d, %d"
  381. , un.name.c_str()
  382. , s_constantTypeName[un.type]
  383. , un.num
  384. , un.regIndex
  385. , un.regCount
  386. );
  387. }
  388. uint16_t shaderSize = (uint16_t)code->GetBufferSize();
  389. stream.write(shaderSize);
  390. stream.write(code->GetBufferPointer(), shaderSize);
  391. uint8_t nul = 0;
  392. stream.write(nul);
  393. stream.close();
  394. fclose(out);
  395. if (NULL != code)
  396. {
  397. code->Release();
  398. }
  399. if (NULL != errorMsg)
  400. {
  401. errorMsg->Release();
  402. }
  403. if (NULL != constantTable)
  404. {
  405. constantTable->Release();
  406. }
  407. return true;
  408. #else
  409. fprintf(stderr, "HLSL compiler is not supported on this platform.\n");
  410. return false;
  411. #endif // BX_PLATFORM_WINDOWS
  412. }
  413. struct Preprocessor
  414. {
  415. Preprocessor(const char* _filePath)
  416. : m_tagptr(m_tags)
  417. , m_scratchPos(0)
  418. , m_fgetsPos(0)
  419. {
  420. m_filePath = scratch(_filePath);
  421. m_tagptr->tag = FPPTAG_USERDATA;
  422. m_tagptr->data = this;
  423. m_tagptr++;
  424. m_tagptr->tag = FPPTAG_DEPENDS;
  425. m_tagptr->data = (void*)fppDepends;
  426. m_tagptr++;
  427. m_tagptr->tag = FPPTAG_INPUT;
  428. m_tagptr->data = (void*)fppInput;
  429. m_tagptr++;
  430. m_tagptr->tag = FPPTAG_OUTPUT;
  431. m_tagptr->data = (void*)fppOutput;
  432. m_tagptr++;
  433. m_tagptr->tag = FPPTAG_ERROR;
  434. m_tagptr->data = (void*)fppError;
  435. m_tagptr++;
  436. m_tagptr->tag = FPPTAG_IGNOREVERSION;
  437. m_tagptr->data = (void*)0;
  438. m_tagptr++;
  439. m_tagptr->tag = FPPTAG_LINE;
  440. m_tagptr->data = (void*)0;
  441. m_tagptr++;
  442. m_tagptr->tag = FPPTAG_INPUT_NAME;
  443. m_tagptr->data = m_filePath;
  444. m_tagptr++;
  445. m_default = "#define lowp\n#define mediump\n#define highp\n";
  446. }
  447. void setDefine(const char* _define)
  448. {
  449. m_tagptr->tag = FPPTAG_DEFINE;
  450. m_tagptr->data = scratch(_define);
  451. m_tagptr++;
  452. }
  453. void setDefaultDefine(const char* _name)
  454. {
  455. char temp[1024];
  456. _snprintf(temp, countof(temp)
  457. , "#ifndef %s\n"
  458. "# define %s 0\n"
  459. "#endif // %s\n"
  460. "\n"
  461. , _name
  462. , _name
  463. , _name
  464. );
  465. m_default += temp;
  466. }
  467. void addDependency(const char* _fileName)
  468. {
  469. m_depends += " \\\n ";
  470. m_depends += _fileName;
  471. }
  472. bool run()
  473. {
  474. m_fgetsPos = 0;
  475. FILE* file = fopen(m_filePath, "r");
  476. if (NULL == file)
  477. {
  478. return false;
  479. }
  480. long int size = fsize(file);
  481. char* input = new char[size+1];
  482. size = fread(input, 1, size, file);
  483. input[size] = '\0';
  484. fclose(file);
  485. m_input = m_default;
  486. m_input += input;
  487. fppTag* tagptr = m_tagptr;
  488. tagptr->tag = FPPTAG_END;
  489. tagptr->data = 0;
  490. tagptr++;
  491. int result = fppPreProcess(m_tags);
  492. return 0 == result;
  493. }
  494. char* fgets(char* _buffer, int _size)
  495. {
  496. int ii = 0;
  497. for (char ch = m_input[m_fgetsPos]; m_fgetsPos < m_input.size() && ii < _size-1; ch = m_input[++m_fgetsPos])
  498. {
  499. _buffer[ii++] = ch;
  500. if (ch == '\n' || ii == _size)
  501. {
  502. _buffer[ii] = '\0';
  503. m_fgetsPos++;
  504. return _buffer;
  505. }
  506. }
  507. return NULL;
  508. }
  509. static void fppDepends(char* _fileName, void* _userData)
  510. {
  511. Preprocessor* thisClass = (Preprocessor*)_userData;
  512. thisClass->addDependency(_fileName);
  513. }
  514. static char* fppInput(char* _buffer, int _size, void* _userData)
  515. {
  516. Preprocessor* thisClass = (Preprocessor*)_userData;
  517. return thisClass->fgets(_buffer, _size);
  518. }
  519. static void fppOutput(int _ch, void* _userData)
  520. {
  521. Preprocessor* thisClass = (Preprocessor*)_userData;
  522. thisClass->m_preprocessed += _ch;
  523. }
  524. static void fppError(void* _userData, char* _format, va_list _vargs)
  525. {
  526. vfprintf(stderr, _format, _vargs);
  527. }
  528. char* scratch(const char* _str)
  529. {
  530. char* result = &m_scratch[m_scratchPos];
  531. strcpy(result, _str);
  532. m_scratchPos += strlen(_str)+1;
  533. return result;
  534. }
  535. fppTag m_tags[MAX_TAGS];
  536. fppTag* m_tagptr;
  537. char* m_filePath;
  538. std::string m_depends;
  539. std::string m_default;
  540. std::string m_input;
  541. std::string m_preprocessed;
  542. char m_scratch[16<<10];
  543. uint32_t m_scratchPos;
  544. uint32_t m_fgetsPos;
  545. };
  546. // OpenGL #version Features Direct3D Features Shader Model
  547. // 2.1 120 vf 9.0 vf 2.0
  548. // 3.0 130
  549. // 3.1 140
  550. // 3.2 150 vgf
  551. // 3.3 330 10.0 vgf 4.0
  552. // 4.0 400 vhdgf
  553. // 4.1 410
  554. // 4.2 420 11.0 vhdgf 5.0
  555. int main(int _argc, const char* _argv[])
  556. {
  557. CommandLine cmdLine(_argc, _argv);
  558. const char* filePath = cmdLine.findOption('f');
  559. if (NULL == filePath)
  560. {
  561. fprintf(stderr, "Shader file name must be specified.\n");
  562. return EXIT_FAILURE;
  563. }
  564. const char* outFilePath = cmdLine.findOption('o');
  565. if (NULL == outFilePath)
  566. {
  567. fprintf(stderr, "Output file name must be specified.\n");
  568. return EXIT_FAILURE;
  569. }
  570. const char* type = cmdLine.findOption('\0', "type");
  571. if (NULL == type)
  572. {
  573. fprintf(stderr, "Must specify shader type.");
  574. return EXIT_FAILURE;
  575. }
  576. const char* platform = cmdLine.findOption('\0', "platform");
  577. if (NULL == platform)
  578. {
  579. fprintf(stderr, "Must specify platform.\n");
  580. return EXIT_FAILURE;
  581. }
  582. bool depends = cmdLine.hasArg("depends");
  583. bool preprocessOnly = cmdLine.hasArg("preprocess");
  584. Preprocessor preprocessor(filePath);
  585. preprocessor.setDefaultDefine("BX_PLATFORM_ANDROID");
  586. preprocessor.setDefaultDefine("BX_PLATFORM_IOS");
  587. preprocessor.setDefaultDefine("BX_PLATFORM_LINUX");
  588. preprocessor.setDefaultDefine("BX_PLATFORM_NACL");
  589. preprocessor.setDefaultDefine("BX_PLATFORM_OSX");
  590. preprocessor.setDefaultDefine("BX_PLATFORM_WINDOWS");
  591. preprocessor.setDefaultDefine("BX_PLATFORM_XBOX360");
  592. preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_GLSL");
  593. preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_HLSL");
  594. preprocessor.setDefaultDefine("BGFX_SHADER_TYPE_FRAGMENT");
  595. preprocessor.setDefaultDefine("BGFX_SHADER_TYPE_VERTEX");
  596. bool glsl = false;
  597. if (0 == _stricmp(platform, "android") )
  598. {
  599. preprocessor.setDefine("BX_PLATFORM_ANDROID=1");
  600. preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
  601. glsl = true;
  602. }
  603. else if (0 == _stricmp(platform, "ios") )
  604. {
  605. preprocessor.setDefine("BX_PLATFORM_IOS=1");
  606. preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
  607. glsl = true;
  608. }
  609. else if (0 == _stricmp(platform, "linux") )
  610. {
  611. preprocessor.setDefine("BX_PLATFORM_IOS=1");
  612. preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
  613. glsl = true;
  614. }
  615. else if (0 == _stricmp(platform, "nacl") )
  616. {
  617. preprocessor.setDefine("BX_PLATFORM_NACL=1");
  618. preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
  619. glsl = true;
  620. }
  621. else if (0 == _stricmp(platform, "osx") )
  622. {
  623. preprocessor.setDefine("BX_PLATFORM_OSX=1");
  624. preprocessor.setDefine("BGFX_SHADER_LANGUAGE_GLSL=1");
  625. glsl = true;
  626. }
  627. else if (0 == _stricmp(platform, "windows") )
  628. {
  629. preprocessor.setDefine("BX_PLATFORM_WINDOWS=1");
  630. preprocessor.setDefine("BGFX_SHADER_LANGUAGE_HLSL=1");
  631. }
  632. else if (0 == _stricmp(platform, "xbox360") )
  633. {
  634. preprocessor.setDefine("BX_PLATFORM_XBOX360=1");
  635. preprocessor.setDefine("BGFX_SHADER_LANGUAGE_HLSL=1");
  636. }
  637. else
  638. {
  639. fprintf(stderr, "Unknown platform %s?!", platform);
  640. return EXIT_FAILURE;
  641. }
  642. switch (tolower(type[0]) )
  643. {
  644. case 'f':
  645. preprocessor.setDefine("BGFX_SHADER_TYPE_FRAGMENT=1");
  646. break;
  647. case 'v':
  648. preprocessor.setDefine("BGFX_SHADER_TYPE_VERTEX=1");
  649. break;
  650. default:
  651. fprintf(stderr, "Unknown type: %s?!", type);
  652. return EXIT_FAILURE;
  653. }
  654. if (preprocessor.run() )
  655. {
  656. BX_TRACE("Input file: %s", filePath);
  657. BX_TRACE("Output file: %s", outFilePath);
  658. if (preprocessOnly)
  659. {
  660. FILE* out = fopen(outFilePath, "wb");
  661. if (NULL == out)
  662. {
  663. fprintf(stderr, "Unable to open output file '%s'.", outFilePath);
  664. return false;
  665. }
  666. Stream stream(out);
  667. if (glsl)
  668. {
  669. const char* profile = cmdLine.findOption('p');
  670. if (NULL == profile)
  671. {
  672. stream.write("#ifdef GL_ES\n");
  673. stream.write("precision highp float;\n");
  674. stream.write("#endif // GL_ES\n\n");
  675. }
  676. else
  677. {
  678. stream.writef("#version %s\n\n", profile);
  679. }
  680. }
  681. stream.write(preprocessor.m_preprocessed.c_str(), preprocessor.m_preprocessed.size() );
  682. stream.close();
  683. fclose(out);
  684. return EXIT_SUCCESS;
  685. }
  686. bool compiled = false;
  687. if (glsl)
  688. {
  689. compiled = compileGLSLShader(cmdLine, preprocessor.m_preprocessed, outFilePath);
  690. }
  691. else
  692. {
  693. compiled = compileHLSLShader(cmdLine, preprocessor.m_preprocessed, outFilePath);
  694. }
  695. if (compiled
  696. && depends)
  697. {
  698. std::string ofp = outFilePath;
  699. ofp += ".d";
  700. FILE* out = fopen(ofp.c_str(), "wb");
  701. if (NULL != out)
  702. {
  703. Stream stream(out);
  704. stream.write(outFilePath);
  705. stream.write(":");
  706. stream.write(preprocessor.m_depends.c_str() );
  707. stream.write("\n");
  708. stream.close();
  709. fclose(out);
  710. }
  711. return EXIT_SUCCESS;
  712. }
  713. }
  714. fprintf(stderr, "Failed to build shader.\n");
  715. return EXIT_FAILURE;
  716. }