ShaderProgramParser.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. // Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/ShaderCompiler/ShaderProgramParser.h>
  6. namespace anki {
  7. #define ANKI_PP_ERROR_MALFORMED() \
  8. ANKI_SHADER_COMPILER_LOGE("%s: Malformed expression: %s", fname.cstr(), line.cstr()); \
  9. return Error::kUserData
  10. #define ANKI_PP_ERROR_MALFORMED_MSG(msg_) \
  11. ANKI_SHADER_COMPILER_LOGE("%s: " msg_ ": %s", fname.cstr(), line.cstr()); \
  12. return Error::kUserData
  13. inline constexpr Array<CString, U32(ShaderType::kCount)> kShaderStageNames = {{"VERTEX", "TESSELLATION_CONTROL", "TESSELLATION_EVALUATION",
  14. "GEOMETRY", "TASK", "MESH", "FRAGMENT", "COMPUTE", "RAY_GEN",
  15. "ANY_HIT", "CLOSEST_HIT", "MISS", "INTERSECTION", "CALLABLE"}};
  16. inline constexpr char kShaderHeader[] = R"(#define ANKI_%s_SHADER 1
  17. #define ANKI_PLATFORM_MOBILE %d
  18. #define ANKI_FORCE_FULL_FP_PRECISION %d
  19. #define kMaxBindlessTextures %uu
  20. #define kMaxBindlessReadonlyTextureBuffers %uu
  21. )";
  22. static const U64 kShaderHeaderHash = computeHash(kShaderHeader, sizeof(kShaderHeader));
  23. static ShaderType strToShaderType(CString str)
  24. {
  25. ShaderType shaderType = ShaderType::kCount;
  26. if(str == "vert")
  27. {
  28. shaderType = ShaderType::kVertex;
  29. }
  30. else if(str == "tessc")
  31. {
  32. shaderType = ShaderType::kTessellationControl;
  33. }
  34. else if(str == "tesse")
  35. {
  36. }
  37. else if(str == "geom")
  38. {
  39. shaderType = ShaderType::kGeometry;
  40. }
  41. else if(str == "task")
  42. {
  43. shaderType = ShaderType::kTask;
  44. }
  45. else if(str == "mesh")
  46. {
  47. shaderType = ShaderType::kMesh;
  48. }
  49. else if(str == "frag")
  50. {
  51. shaderType = ShaderType::kFragment;
  52. }
  53. else if(str == "comp")
  54. {
  55. shaderType = ShaderType::kCompute;
  56. }
  57. else if(str == "rgen")
  58. {
  59. shaderType = ShaderType::kRayGen;
  60. }
  61. else if(str == "ahit")
  62. {
  63. shaderType = ShaderType::kAnyHit;
  64. }
  65. else if(str == "chit")
  66. {
  67. shaderType = ShaderType::kClosestHit;
  68. }
  69. else if(str == "miss")
  70. {
  71. shaderType = ShaderType::kMiss;
  72. }
  73. else if(str == "int")
  74. {
  75. shaderType = ShaderType::kIntersection;
  76. }
  77. else if(str == "call")
  78. {
  79. shaderType = ShaderType::kCallable;
  80. }
  81. else
  82. {
  83. shaderType = ShaderType::kCount;
  84. }
  85. return shaderType;
  86. }
  87. ShaderProgramParser::ShaderProgramParser(CString fname, ShaderProgramFilesystemInterface* fsystem, const ShaderCompilerOptions& compilerOptions)
  88. : m_fname(fname)
  89. , m_fsystem(fsystem)
  90. , m_compilerOptions(compilerOptions)
  91. {
  92. }
  93. ShaderProgramParser::~ShaderProgramParser()
  94. {
  95. }
  96. void ShaderProgramParser::tokenizeLine(CString line, ShaderCompilerDynamicArray<ShaderCompilerString>& tokens) const
  97. {
  98. ANKI_ASSERT(line.getLength() > 0);
  99. ShaderCompilerString l = line;
  100. // Replace all tabs with spaces
  101. for(char& c : l)
  102. {
  103. if(c == '\t')
  104. {
  105. c = ' ';
  106. }
  107. }
  108. // Split
  109. ShaderCompilerStringList spaceTokens;
  110. spaceTokens.splitString(l, ' ', false);
  111. // Create the array
  112. for(const ShaderCompilerString& s : spaceTokens)
  113. {
  114. tokens.emplaceBack(s);
  115. }
  116. }
  117. Error ShaderProgramParser::parsePragmaTechniqueStart(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  118. {
  119. ANKI_ASSERT(begin && end);
  120. const PtrSize tokenCount = end - begin;
  121. if(tokenCount != 1 && tokenCount != 2)
  122. {
  123. ANKI_PP_ERROR_MALFORMED();
  124. }
  125. const ShaderType shaderType = strToShaderType(*begin);
  126. if(shaderType == ShaderType::kCount)
  127. {
  128. ANKI_PP_ERROR_MALFORMED();
  129. }
  130. ShaderCompilerString techniqueName;
  131. ++begin;
  132. if(begin == end)
  133. {
  134. // Last token
  135. techniqueName = "Unnamed";
  136. }
  137. else
  138. {
  139. techniqueName = *begin;
  140. ++begin;
  141. if(begin != end)
  142. {
  143. ANKI_PP_ERROR_MALFORMED();
  144. }
  145. }
  146. // Checks
  147. if(insideTechnique())
  148. {
  149. ANKI_PP_ERROR_MALFORMED_MSG("Need to close the previous technique_start before starting a new one");
  150. }
  151. // Find the technique
  152. Technique* technique = nullptr;
  153. for(Technique& t : m_techniques)
  154. {
  155. if(t.m_name == techniqueName)
  156. {
  157. if(!!(t.m_shaderTypes & ShaderTypeBit(1 << shaderType)))
  158. {
  159. ANKI_PP_ERROR_MALFORMED_MSG("technique_start with the same name and type appeared more than once");
  160. }
  161. technique = &t;
  162. break;
  163. }
  164. }
  165. // Done
  166. TechniqueExtra* extra = nullptr;
  167. if(!technique)
  168. {
  169. technique = m_techniques.emplaceBack();
  170. technique->m_name = techniqueName;
  171. extra = m_techniqueExtras.emplaceBack();
  172. }
  173. else
  174. {
  175. const U32 idx = U32(technique - m_techniques.getBegin());
  176. extra = &m_techniqueExtras[idx];
  177. }
  178. technique->m_shaderTypes |= ShaderTypeBit(1 << shaderType);
  179. ANKI_ASSERT(extra->m_sourceLines[shaderType].getSize() == 0);
  180. extra->m_sourceLines[shaderType] = m_commonSourceLines;
  181. extra->m_sourceLines[shaderType].pushBackSprintf("#define ANKI_%s_SHADER 1", kShaderStageNames[shaderType].cstr());
  182. extra->m_sourceLines[shaderType].pushBackSprintf("#define ANKI_TECHNIQUE_%s 1", techniqueName.cstr());
  183. m_insideTechniqueIdx = U32(technique - m_techniques.getBegin());
  184. m_insideTechniqueShaderType = shaderType;
  185. return Error::kNone;
  186. }
  187. Error ShaderProgramParser::parsePragmaTechniqueEnd(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  188. {
  189. ANKI_ASSERT(begin && end);
  190. // Check tokens
  191. if(begin >= end)
  192. {
  193. ANKI_PP_ERROR_MALFORMED();
  194. }
  195. const ShaderType shaderType = strToShaderType(*begin);
  196. if(shaderType == ShaderType::kCount)
  197. {
  198. ANKI_PP_ERROR_MALFORMED();
  199. }
  200. ShaderCompilerString techniqueName;
  201. ++begin;
  202. if(begin == end)
  203. {
  204. // Last token
  205. techniqueName = "Unnamed";
  206. }
  207. else
  208. {
  209. techniqueName = *begin;
  210. ++begin;
  211. if(begin != end)
  212. {
  213. ANKI_PP_ERROR_MALFORMED();
  214. }
  215. }
  216. // Checks
  217. if(!insideTechnique())
  218. {
  219. ANKI_PP_ERROR_MALFORMED_MSG("Forgot to insert a #pragma anki technique_start");
  220. }
  221. if(m_techniques.getBack().m_name != techniqueName || m_insideTechniqueShaderType != shaderType)
  222. {
  223. ANKI_PP_ERROR_MALFORMED_MSG("name or type doesn't match the one in technique_start");
  224. }
  225. // Done
  226. m_insideTechniqueIdx = kMaxU32;
  227. m_insideTechniqueShaderType = ShaderType::kCount;
  228. return Error::kNone;
  229. }
  230. Error ShaderProgramParser::parsePragmaMutator(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  231. {
  232. ANKI_ASSERT(begin && end);
  233. if(begin >= end)
  234. {
  235. ANKI_PP_ERROR_MALFORMED();
  236. }
  237. m_mutators.emplaceBack();
  238. Mutator& mutator = m_mutators.getBack();
  239. // Name
  240. {
  241. if(begin >= end)
  242. {
  243. // Need to have a name
  244. ANKI_PP_ERROR_MALFORMED();
  245. }
  246. // Check for duplicate mutators
  247. for(U32 i = 0; i < m_mutators.getSize() - 1; ++i)
  248. {
  249. if(m_mutators[i].m_name == *begin)
  250. {
  251. ANKI_PP_ERROR_MALFORMED_MSG("Duplicate mutator");
  252. }
  253. }
  254. if(begin->getLength() > kMaxShaderBinaryNameLength)
  255. {
  256. ANKI_PP_ERROR_MALFORMED_MSG("Too big name");
  257. }
  258. mutator.m_name = *begin;
  259. ++begin;
  260. }
  261. // Values
  262. {
  263. // Gather them
  264. for(; begin < end; ++begin)
  265. {
  266. MutatorValue value = 0;
  267. if(tokenIsComment(begin->toCString()))
  268. {
  269. break;
  270. }
  271. if(begin->toNumber(value))
  272. {
  273. ANKI_PP_ERROR_MALFORMED();
  274. }
  275. mutator.m_values.emplaceBack(value);
  276. }
  277. std::sort(mutator.m_values.getBegin(), mutator.m_values.getEnd());
  278. // Check for duplicates
  279. for(U32 i = 1; i < mutator.m_values.getSize(); ++i)
  280. {
  281. if(mutator.m_values[i - 1] == mutator.m_values[i])
  282. {
  283. ANKI_PP_ERROR_MALFORMED_MSG("Same value appeared more than once");
  284. }
  285. }
  286. }
  287. return Error::kNone;
  288. }
  289. Error ShaderProgramParser::parsePragmaSkipMutation(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  290. {
  291. ANKI_ASSERT(begin && end);
  292. // Some basic sanity checks
  293. const U tokenCount = U(end - begin);
  294. // One pair doesn't make sence so it's: mutator_name_0 + mutator_value_0 + mutator_name_1 + mutator_value_1
  295. constexpr U minTokenCount = 2 + 2;
  296. if(tokenCount < minTokenCount || (tokenCount % 2) != 0)
  297. {
  298. ANKI_PP_ERROR_MALFORMED();
  299. }
  300. PartialMutationSkip& skip = *m_skipMutations.emplaceBack();
  301. skip.m_partialMutation.resize(m_mutators.getSize(), std::numeric_limits<MutatorValue>::max());
  302. do
  303. {
  304. // Get mutator name
  305. const CString mutatorName = *begin;
  306. U32 mutatorIndex = kMaxU32;
  307. for(U32 i = 0; i < m_mutators.getSize(); ++i)
  308. {
  309. if(m_mutators[i].m_name == mutatorName)
  310. {
  311. mutatorIndex = i;
  312. break;
  313. }
  314. }
  315. if(mutatorIndex == kMaxU32)
  316. {
  317. ANKI_PP_ERROR_MALFORMED_MSG("Mutator not found");
  318. }
  319. // Get mutator value
  320. ++begin;
  321. const CString valueStr = *begin;
  322. MutatorValue value;
  323. if(valueStr.toNumber(value))
  324. {
  325. ANKI_PP_ERROR_MALFORMED_MSG("Malformed mutator value");
  326. }
  327. if(!mutatorHasValue(m_mutators[mutatorIndex], value))
  328. {
  329. ANKI_PP_ERROR_MALFORMED_MSG("Mutator value incorrect");
  330. }
  331. skip.m_partialMutation[mutatorIndex] = value;
  332. ++begin;
  333. } while(begin < end && !tokenIsComment(*begin));
  334. return Error::kNone;
  335. }
  336. Error ShaderProgramParser::parseInclude(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname, U32 depth)
  337. {
  338. // Gather the path
  339. ShaderCompilerString path;
  340. for(; begin < end; ++begin)
  341. {
  342. path += *begin;
  343. }
  344. if(path.isEmpty())
  345. {
  346. ANKI_PP_ERROR_MALFORMED();
  347. }
  348. // Check
  349. const char firstChar = path[0];
  350. const char lastChar = path[path.getLength() - 1];
  351. if((firstChar == '\"' && lastChar == '\"') || (firstChar == '<' && lastChar == '>'))
  352. {
  353. ShaderCompilerString fname2(path.begin() + 1, path.begin() + path.getLength() - 1);
  354. const Bool dontIgnore =
  355. fname2.find("AnKi/Shaders/") != ShaderCompilerString::kNpos || fname2.find("ThirdParty/") != ShaderCompilerString::kNpos;
  356. if(!dontIgnore)
  357. {
  358. // The shaders can't include C++ files. Ignore the include
  359. return Error::kNone;
  360. }
  361. if(parseFile(fname2, depth + 1))
  362. {
  363. ANKI_PP_ERROR_MALFORMED_MSG("Error parsing include. See previous errors");
  364. }
  365. }
  366. else
  367. {
  368. ANKI_PP_ERROR_MALFORMED();
  369. }
  370. return Error::kNone;
  371. }
  372. Error ShaderProgramParser::parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth, U32 lineNo)
  373. {
  374. // Tokenize
  375. ShaderCompilerDynamicArray<ShaderCompilerString> tokens;
  376. tokenizeLine(line, tokens);
  377. ANKI_ASSERT(tokens.getSize() > 0);
  378. const ShaderCompilerString* token = tokens.getBegin();
  379. const ShaderCompilerString* end = tokens.getEnd();
  380. // Skip the hash
  381. Bool foundAloneHash = false;
  382. if(*token == "#")
  383. {
  384. ++token;
  385. foundAloneHash = true;
  386. }
  387. if((token < end) && ((foundAloneHash && *token == "include") || *token == "#include"))
  388. {
  389. // We _must_ have an #include
  390. ANKI_CHECK(parseInclude(token + 1, end, line, fname, depth));
  391. getAppendSourceList().pushBackSprintf("#line %u \"%s\"", lineNo + 1, fname.cstr());
  392. }
  393. else if((token < end) && ((foundAloneHash && *token == "pragma") || *token == "#pragma"))
  394. {
  395. // We may have a #pragma once or a #pragma anki or something else
  396. ++token;
  397. if(*token == "once")
  398. {
  399. // Pragma once
  400. if(foundPragmaOnce)
  401. {
  402. ANKI_PP_ERROR_MALFORMED_MSG("Can't have more than one #pragma once per file");
  403. }
  404. if(token + 1 != end)
  405. {
  406. ANKI_PP_ERROR_MALFORMED();
  407. }
  408. // Add the guard unique for this file
  409. foundPragmaOnce = true;
  410. const U64 hash = fname.computeHash();
  411. getAppendSourceList().pushBackSprintf("#ifndef _ANKI_INCL_GUARD_%" PRIu64 "\n"
  412. "#define _ANKI_INCL_GUARD_%" PRIu64,
  413. hash, hash);
  414. getAppendSourceList().pushBackSprintf("#line %u \"%s\"", lineNo + 1, fname.cstr());
  415. }
  416. else if(*token == "anki")
  417. {
  418. // Must be a #pragma anki
  419. ++token;
  420. if(*token == "mutator")
  421. {
  422. ANKI_CHECK(checkNoActiveStruct());
  423. ANKI_CHECK(parsePragmaMutator(token + 1, end, line, fname));
  424. }
  425. else if(*token == "technique_start")
  426. {
  427. ANKI_CHECK(checkNoActiveStruct());
  428. ANKI_CHECK(parsePragmaTechniqueStart(token + 1, end, line, fname));
  429. }
  430. else if(*token == "technique_end")
  431. {
  432. ANKI_CHECK(checkNoActiveStruct());
  433. ANKI_CHECK(parsePragmaTechniqueEnd(token + 1, end, line, fname));
  434. }
  435. else if(*token == "skip_mutation")
  436. {
  437. ANKI_CHECK(checkNoActiveStruct());
  438. ANKI_CHECK(parsePragmaSkipMutation(token + 1, end, line, fname));
  439. }
  440. else if(*token == "struct")
  441. {
  442. ANKI_CHECK(checkNoActiveStruct());
  443. ANKI_CHECK(parsePragmaStructBegin(token + 1, end, line, fname));
  444. }
  445. else if(*token == "struct_end")
  446. {
  447. ANKI_CHECK(checkActiveStruct());
  448. ANKI_CHECK(parsePragmaStructEnd(token + 1, end, line, fname));
  449. }
  450. else if(*token == "member")
  451. {
  452. ANKI_CHECK(checkActiveStruct());
  453. ANKI_CHECK(parsePragmaMember(token + 1, end, line, fname));
  454. }
  455. else if(*token == "16bit")
  456. {
  457. ANKI_CHECK(parsePragma16bit(token + 1, end, line, fname));
  458. }
  459. else
  460. {
  461. ANKI_PP_ERROR_MALFORMED();
  462. }
  463. // For good measure
  464. getAppendSourceList().pushBackSprintf("#line %u \"%s\"", lineNo + 1, fname.cstr());
  465. }
  466. else
  467. {
  468. // Some other pragma, ignore
  469. getAppendSourceList().pushBack(line);
  470. }
  471. }
  472. else
  473. {
  474. // Ignore
  475. getAppendSourceList().pushBack(line);
  476. }
  477. return Error::kNone;
  478. }
  479. Error ShaderProgramParser::parsePragmaStructBegin(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  480. {
  481. const U tokenCount = U(end - begin);
  482. if(tokenCount != 1)
  483. {
  484. ANKI_PP_ERROR_MALFORMED();
  485. }
  486. GhostStruct& gstruct = *m_ghostStructs.emplaceBack();
  487. gstruct.m_name = *begin;
  488. getAppendSourceList().pushBackSprintf("struct %s {", begin->cstr());
  489. ANKI_ASSERT(!m_insideStruct);
  490. m_insideStruct = true;
  491. return Error::kNone;
  492. }
  493. Error ShaderProgramParser::parsePragmaMember(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  494. {
  495. ANKI_ASSERT(m_insideStruct);
  496. const U tokenCount = U(end - begin);
  497. if(tokenCount != 2)
  498. {
  499. ANKI_PP_ERROR_MALFORMED();
  500. }
  501. GhostStruct& structure = m_ghostStructs.getBack();
  502. Member member;
  503. // Type
  504. const CString typeStr = *begin;
  505. member.m_type = ShaderVariableDataType::kNone;
  506. if(typeStr == "F32" || typeStr == "RF32")
  507. {
  508. member.m_type = ShaderVariableDataType::kF32;
  509. }
  510. else if(typeStr == "Vec2" || typeStr == "RVec2")
  511. {
  512. member.m_type = ShaderVariableDataType::kVec2;
  513. }
  514. else if(typeStr == "Vec3" || typeStr == "RVec3")
  515. {
  516. member.m_type = ShaderVariableDataType::kVec3;
  517. }
  518. else if(typeStr == "Vec4" || typeStr == "RVec4")
  519. {
  520. member.m_type = ShaderVariableDataType::kVec4;
  521. }
  522. else if(typeStr == "U32")
  523. {
  524. member.m_type = ShaderVariableDataType::kU32;
  525. }
  526. if(member.m_type == ShaderVariableDataType::kNone)
  527. {
  528. ANKI_PP_ERROR_MALFORMED_MSG("Unrecognized type");
  529. }
  530. // Name
  531. ++begin;
  532. member.m_name = *begin;
  533. // Rest
  534. member.m_offset = (structure.m_members.getSize())
  535. ? structure.m_members.getBack().m_offset + getShaderVariableDataTypeInfo(structure.m_members.getBack().m_type).m_size
  536. : 0;
  537. getAppendSourceList().pushBackSprintf("#define %s_%s_OFFSETOF %u", structure.m_name.cstr(), member.m_name.cstr(), member.m_offset);
  538. getAppendSourceList().pushBackSprintf("\t%s %s;", typeStr.cstr(), member.m_name.cstr());
  539. structure.m_members.emplaceBack(std::move(member));
  540. return Error::kNone;
  541. }
  542. Error ShaderProgramParser::parsePragmaStructEnd(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  543. {
  544. ANKI_ASSERT(m_insideStruct);
  545. if(begin != end)
  546. {
  547. ANKI_PP_ERROR_MALFORMED();
  548. }
  549. GhostStruct& gstruct = m_ghostStructs.getBack();
  550. const CString structName = gstruct.m_name;
  551. if(gstruct.m_members.isEmpty())
  552. {
  553. ANKI_PP_ERROR_MALFORMED_MSG("Struct doesn't have any members");
  554. }
  555. getAppendSourceList().pushBack("};");
  556. for(U32 i = 0; i < gstruct.m_members.getSize(); ++i)
  557. {
  558. const Member& m = gstruct.m_members[i];
  559. // # define XXX_LOAD()
  560. getAppendSourceList().pushBackSprintf("#\tdefine %s_%s_LOAD(buff, offset) buff.Load<%s>(%s_%s_OFFSETOF + (offset))%s", structName.cstr(),
  561. m.m_name.cstr(), getShaderVariableDataTypeInfo(m.m_type).m_name, structName.cstr(), m.m_name.cstr(),
  562. (i != gstruct.m_members.getSize() - 1) ? "," : "");
  563. }
  564. // Now define the structure LOAD in HLSL
  565. getAppendSourceList().pushBackSprintf("#define load%s(buff, offset) { \\", structName.cstr());
  566. for(U32 i = 0; i < gstruct.m_members.getSize(); ++i)
  567. {
  568. const Member& m = gstruct.m_members[i];
  569. getAppendSourceList().pushBackSprintf("\t%s_%s_LOAD(buff, offset) \\", structName.cstr(), m.m_name.cstr());
  570. }
  571. getAppendSourceList().pushBack("}");
  572. // Done
  573. m_insideStruct = false;
  574. return Error::kNone;
  575. }
  576. Error ShaderProgramParser::parsePragma16bit(const ShaderCompilerString* begin, const ShaderCompilerString* end, CString line, CString fname)
  577. {
  578. ANKI_ASSERT(begin && end);
  579. // Check tokens
  580. if(begin != end)
  581. {
  582. ANKI_PP_ERROR_MALFORMED();
  583. }
  584. m_16bitTypes = true;
  585. return Error::kNone;
  586. }
  587. Error ShaderProgramParser::parseFile(CString fname, U32 depth)
  588. {
  589. // First check the depth
  590. if(depth > kMaxIncludeDepth)
  591. {
  592. ANKI_SHADER_COMPILER_LOGE("The include depth is too high. Probably circular includance");
  593. }
  594. Bool foundPragmaOnce = false;
  595. // Load file in lines
  596. ShaderCompilerString txt;
  597. ANKI_CHECK(m_fsystem->readAllText(fname, txt));
  598. m_hash = (m_hash) ? computeHash(txt.cstr(), txt.getLength()) : appendHash(txt.cstr(), txt.getLength(), m_hash);
  599. ShaderCompilerStringList lines;
  600. lines.splitString(txt, '\n', true);
  601. if(lines.getSize() < 1)
  602. {
  603. ANKI_SHADER_COMPILER_LOGE("Source is empty");
  604. }
  605. getAppendSourceList().pushBackSprintf("#line 0 \"%s\"", fname.cstr());
  606. // Parse lines
  607. U32 lineNo = 1;
  608. for(const ShaderCompilerString& line : lines)
  609. {
  610. if(line.isEmpty())
  611. {
  612. getAppendSourceList().pushBack(" ");
  613. }
  614. else if(line.find("pragma") != ShaderCompilerString::kNpos || line.find("include") != ShaderCompilerString::kNpos)
  615. {
  616. // Possibly a preprocessor directive we care
  617. ANKI_CHECK(parseLine(line.toCString(), fname, foundPragmaOnce, depth, lineNo));
  618. }
  619. else
  620. {
  621. // Just append the line
  622. getAppendSourceList().pushBack(line.toCString());
  623. }
  624. ++lineNo;
  625. }
  626. if(foundPragmaOnce)
  627. {
  628. // Append the guard
  629. getAppendSourceList().pushBack("#endif // Include guard");
  630. }
  631. return Error::kNone;
  632. }
  633. Error ShaderProgramParser::parse()
  634. {
  635. ANKI_ASSERT(!m_fname.isEmpty());
  636. ANKI_ASSERT(m_commonSourceLines.isEmpty());
  637. const CString fname = m_fname;
  638. // Parse recursively
  639. ANKI_CHECK(parseFile(fname, 0));
  640. // Checks
  641. {
  642. if(m_techniques.getSize() == 0)
  643. {
  644. ANKI_SHADER_COMPILER_LOGE("No techniques were found");
  645. return Error::kUserData;
  646. }
  647. if(insideTechnique())
  648. {
  649. ANKI_SHADER_COMPILER_LOGE("Forgot to end a technique");
  650. return Error::kUserData;
  651. }
  652. if(m_insideStruct)
  653. {
  654. ANKI_SHADER_COMPILER_LOGE("Forgot to end a struct");
  655. return Error::kUserData;
  656. }
  657. }
  658. // Create the code lines for each technique
  659. for(U32 i = 0; i < m_techniques.getSize(); ++i)
  660. {
  661. for(ShaderType s : EnumIterable<ShaderType>())
  662. {
  663. if(m_techniqueExtras[i].m_sourceLines[s].getSize())
  664. {
  665. ANKI_ASSERT(!!(m_techniques[i].m_shaderTypes & ShaderTypeBit(1 << s)));
  666. m_techniqueExtras[i].m_sourceLines[s].join("\n", m_techniqueExtras[i].m_sources[s]);
  667. m_techniqueExtras[i].m_sourceLines[s].destroy(); // Free mem
  668. }
  669. else
  670. {
  671. ANKI_ASSERT(!(m_techniques[i].m_shaderTypes & ShaderTypeBit(1 << s)));
  672. }
  673. }
  674. }
  675. m_commonSourceLines.destroy(); // Free mem
  676. return Error::kNone;
  677. }
  678. void ShaderProgramParser::generateAnkiShaderHeader(ShaderType shaderType, const ShaderCompilerOptions& compilerOptions, ShaderCompilerString& header)
  679. {
  680. header.sprintf(kShaderHeader, kShaderStageNames[shaderType].cstr(), compilerOptions.m_mobilePlatform,
  681. compilerOptions.m_forceFullFloatingPointPrecision, kMaxBindlessTextures, kMaxBindlessReadonlyTextureBuffers);
  682. }
  683. void ShaderProgramParser::generateVariant(ConstWeakArray<MutatorValue> mutation, const ShaderProgramParserTechnique& technique, ShaderType shaderType,
  684. ShaderCompilerString& source) const
  685. {
  686. // Sanity checks
  687. ANKI_ASSERT(mutation.getSize() == m_mutators.getSize());
  688. for(U32 i = 0; i < mutation.getSize(); ++i)
  689. {
  690. ANKI_ASSERT(mutatorHasValue(m_mutators[i], mutation[i]) && "Value not found");
  691. }
  692. ANKI_ASSERT(!!(technique.m_shaderTypes & ShaderTypeBit(1 << shaderType)));
  693. source.destroy();
  694. for(U32 i = 0; i < mutation.getSize(); ++i)
  695. {
  696. source += ShaderCompilerString().sprintf("#define %s %d\n", m_mutators[i].m_name.cstr(), mutation[i]);
  697. }
  698. source += ShaderCompilerString().sprintf("#define ANKI_TECHNIQUE_%s 1\n", technique.m_name.cstr());
  699. ShaderCompilerString header;
  700. generateAnkiShaderHeader(shaderType, m_compilerOptions, header);
  701. source += header;
  702. if(m_16bitTypes)
  703. {
  704. source += "#define ANKI_SUPPORTS_16BIT_TYPES 1\n";
  705. }
  706. else
  707. {
  708. source += "#define ANKI_SUPPORTS_16BIT_TYPES 0\n";
  709. }
  710. ANKI_ASSERT(&technique >= m_techniques.getBegin() && &technique < m_techniques.getEnd());
  711. const U32 tIdx = U32(&technique - m_techniques.getBegin());
  712. ANKI_ASSERT(m_techniqueExtras[tIdx].m_sources[shaderType].getLength() > 0);
  713. source += m_techniqueExtras[tIdx].m_sources[shaderType];
  714. }
  715. Bool ShaderProgramParser::mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value)
  716. {
  717. for(MutatorValue v : mutator.m_values)
  718. {
  719. if(value == v)
  720. {
  721. return true;
  722. }
  723. }
  724. return false;
  725. }
  726. Bool ShaderProgramParser::skipMutation(ConstWeakArray<MutatorValue> mutation) const
  727. {
  728. ANKI_ASSERT(mutation.getSize() == m_mutators.getSize());
  729. for(const PartialMutationSkip& skip : m_skipMutations)
  730. {
  731. Bool doSkip = true;
  732. for(U32 i = 0; i < m_mutators.getSize(); ++i)
  733. {
  734. if(skip.m_partialMutation[i] == std::numeric_limits<MutatorValue>::max())
  735. {
  736. // Don't care
  737. continue;
  738. }
  739. if(skip.m_partialMutation[i] != mutation[i])
  740. {
  741. doSkip = false;
  742. break;
  743. }
  744. }
  745. if(doSkip)
  746. {
  747. return true;
  748. }
  749. }
  750. return false;
  751. }
  752. } // end namespace anki