ShaderProgramParser.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. // Copyright (C) 2009-2020, 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/shader_compiler/ShaderProgramParser.h>
  6. namespace anki
  7. {
  8. #define ANKI_PP_ERROR_MALFORMED() \
  9. ANKI_SHADER_COMPILER_LOGE("%s: Malformed expression: %s", fname.cstr(), line.cstr()); \
  10. return Error::USER_DATA
  11. #define ANKI_PP_ERROR_MALFORMED_MSG(msg_) \
  12. ANKI_SHADER_COMPILER_LOGE("%s: " msg_ ": %s", fname.cstr(), line.cstr()); \
  13. return Error::USER_DATA
  14. static const Array<CString, U32(ShaderType::COUNT)> SHADER_STAGE_NAMES = {
  15. {"VERTEX", "TESSELLATION_CONTROL", "TESSELLATION_EVALUATION", "GEOMETRY", "FRAGMENT", "COMPUTE"}};
  16. static const char* SHADER_HEADER = R"(#version 450 core
  17. #define ANKI_BACKEND_MINOR %u
  18. #define ANKI_BACKEND_MAJOR %u
  19. #define ANKI_VENDOR_%s 1
  20. #define gl_VertexID gl_VertexIndex
  21. #define gl_InstanceID gl_InstanceIndex
  22. #extension GL_EXT_control_flow_attributes : require
  23. #define ANKI_UNROLL [[unroll]]
  24. #define ANKI_LOOP [[dont_unroll]]
  25. #define ANKI_BRANCH [[branch]]
  26. #define ANKI_FLATTEN [[flatten]]
  27. #extension GL_KHR_shader_subgroup_vote : require
  28. #extension GL_KHR_shader_subgroup_ballot : require
  29. #extension GL_KHR_shader_subgroup_shuffle : require
  30. #extension GL_KHR_shader_subgroup_arithmetic : require
  31. #extension GL_EXT_samplerless_texture_functions : require
  32. #extension GL_EXT_shader_image_load_formatted : require
  33. #extension GL_EXT_nonuniform_qualifier : enable
  34. #define ANKI_MAX_BINDLESS_TEXTURES %u
  35. #define ANKI_MAX_BINDLESS_IMAGES %u
  36. #define F32 float
  37. #define Vec2 vec2
  38. #define Vec3 vec3
  39. #define Vec4 vec4
  40. #define U32 uint
  41. #define UVec2 uvec2
  42. #define UVec3 uvec3
  43. #define UVec4 uvec4
  44. #define I32 int
  45. #define IVec2 ivec2
  46. #define IVec3 ivec3
  47. #define IVec4 ivec4
  48. #define Mat3 mat3
  49. #define Mat4 mat4
  50. #define Mat3x4 mat3x4
  51. #define Bool bool
  52. #define _ANKI_CONCATENATE(a, b) a##b
  53. #define ANKI_CONCATENATE(a, b) _ANKI_CONCATENATE(a, b)
  54. #define ANKI_SPECIALIZATION_CONSTANT_I32(x, id, defltVal) layout(constant_id = id) const I32 x = defltVal
  55. #define ANKI_SPECIALIZATION_CONSTANT_IVEC2(x, id, defltVal) \
  56. layout(constant_id = id) const I32 ANKI_CONCATENATE(x, _0) = defltVal[0]; \
  57. layout(constant_id = id + 1) const I32 ANKI_CONCATENATE(x, _1) = defltVal[1]
  58. #define ANKI_SPECIALIZATION_CONSTANT_IVEC3(x, id, defltVal) \
  59. layout(constant_id = id) const I32 ANKI_CONCATENATE(x, _0) = defltVal[0]; \
  60. layout(constant_id = id + 1) const I32 ANKI_CONCATENATE(x, _1) = defltVal[1]; \
  61. layout(constant_id = id + 2) const I32 ANKI_CONCATENATE(x, _2) = defltVal[2]
  62. #define ANKI_SPECIALIZATION_CONSTANT_F32(x, id, defltVal) layout(constant_id = id) const F32 x = defltVal
  63. #define ANKI_SPECIALIZATION_CONSTANT_VEC2(x, id, defltVal) \
  64. layout(constant_id = id) const F32 ANKI_CONCATENATE(x, _0) = defltVal[0]; \
  65. layout(constant_id = id + 1) const F32 ANKI_CONCATENATE(x, _1) = defltVal[1]
  66. #define ANKI_SPECIALIZATION_CONSTANT_VEC3(x, id, defltVal) \
  67. layout(constant_id = id) const F32 ANKI_CONCATENATE(x, _0) = defltVal[0]; \
  68. layout(constant_id = id + 1) const F32 ANKI_CONCATENATE(x, _1) = defltVal[1]; \
  69. layout(constant_id = id + 2) const F32 ANKI_CONCATENATE(x, _2) = defltVal[2]
  70. )";
  71. ShaderProgramParser::ShaderProgramParser(CString fname,
  72. ShaderProgramFilesystemInterface* fsystem,
  73. GenericMemoryPoolAllocator<U8> alloc,
  74. U32 pushConstantsSize,
  75. U32 backendMinor,
  76. U32 backendMajor,
  77. GpuVendor gpuVendor,
  78. const BindlessLimits& bindlessLimits)
  79. : m_alloc(alloc)
  80. , m_fname(alloc, fname)
  81. , m_fsystem(fsystem)
  82. , m_pushConstSize(pushConstantsSize)
  83. , m_backendMinor(backendMinor)
  84. , m_backendMajor(backendMajor)
  85. , m_gpuVendor(gpuVendor)
  86. , m_bindlessLimits(bindlessLimits)
  87. {
  88. }
  89. ShaderProgramParser::~ShaderProgramParser()
  90. {
  91. }
  92. void ShaderProgramParser::tokenizeLine(CString line, DynamicArrayAuto<StringAuto>& tokens) const
  93. {
  94. ANKI_ASSERT(line.getLength() > 0);
  95. StringAuto l(m_alloc, line);
  96. // Replace all tabs with spaces
  97. for(char& c : l)
  98. {
  99. if(c == '\t')
  100. {
  101. c = ' ';
  102. }
  103. }
  104. // Split
  105. StringListAuto spaceTokens(m_alloc);
  106. spaceTokens.splitString(l, ' ', false);
  107. // Create the array
  108. for(const String& s : spaceTokens)
  109. {
  110. tokens.emplaceBack(m_alloc, s);
  111. }
  112. }
  113. Error ShaderProgramParser::parsePragmaStart(const StringAuto* begin, const StringAuto* end, CString line, CString fname)
  114. {
  115. ANKI_ASSERT(begin && end);
  116. if(begin >= end)
  117. {
  118. ANKI_PP_ERROR_MALFORMED();
  119. }
  120. ShaderType shaderType = ShaderType::COUNT;
  121. if(*begin == "vert")
  122. {
  123. shaderType = ShaderType::VERTEX;
  124. }
  125. else if(*begin == "tessc")
  126. {
  127. shaderType = ShaderType::TESSELLATION_CONTROL;
  128. }
  129. else if(*begin == "tesse")
  130. {
  131. }
  132. else if(*begin == "geom")
  133. {
  134. shaderType = ShaderType::GEOMETRY;
  135. }
  136. else if(*begin == "frag")
  137. {
  138. shaderType = ShaderType::FRAGMENT;
  139. }
  140. else if(*begin == "comp")
  141. {
  142. shaderType = ShaderType::COMPUTE;
  143. }
  144. else
  145. {
  146. ANKI_PP_ERROR_MALFORMED();
  147. }
  148. m_codeLines.pushBackSprintf("#ifdef ANKI_%s", SHADER_STAGE_NAMES[shaderType].cstr());
  149. ++begin;
  150. if(begin != end)
  151. {
  152. // Should be the last token
  153. ANKI_PP_ERROR_MALFORMED();
  154. }
  155. // Set the mask
  156. ShaderTypeBit mask = ShaderTypeBit(1 << U(shaderType));
  157. if(!!(mask & m_shaderTypes))
  158. {
  159. ANKI_PP_ERROR_MALFORMED_MSG("Can't have #pragma start <shader> appearing more than once");
  160. }
  161. m_shaderTypes |= mask;
  162. // Check bounds
  163. if(m_insideShader)
  164. {
  165. ANKI_PP_ERROR_MALFORMED_MSG("Can't have #pragma start before you close the previous pragma start");
  166. }
  167. m_insideShader = true;
  168. return Error::NONE;
  169. }
  170. Error ShaderProgramParser::parsePragmaEnd(const StringAuto* begin, const StringAuto* end, CString line, CString fname)
  171. {
  172. ANKI_ASSERT(begin && end);
  173. // Check tokens
  174. if(begin != end)
  175. {
  176. ANKI_PP_ERROR_MALFORMED();
  177. }
  178. // Check bounds
  179. if(!m_insideShader)
  180. {
  181. ANKI_PP_ERROR_MALFORMED_MSG("Can't have #pragma end before you open with a pragma start");
  182. }
  183. m_insideShader = false;
  184. // Write code
  185. m_codeLines.pushBack("#endif // Shader guard");
  186. return Error::NONE;
  187. }
  188. Error ShaderProgramParser::parsePragmaMutator(
  189. const StringAuto* begin, const StringAuto* end, CString line, CString fname)
  190. {
  191. ANKI_ASSERT(begin && end);
  192. if(begin >= end)
  193. {
  194. ANKI_PP_ERROR_MALFORMED();
  195. }
  196. m_mutators.emplaceBack(m_alloc);
  197. Mutator& mutator = m_mutators.getBack();
  198. // Name
  199. {
  200. if(begin >= end)
  201. {
  202. // Need to have a name
  203. ANKI_PP_ERROR_MALFORMED();
  204. }
  205. // Check for duplicate mutators
  206. for(U32 i = 0; i < m_mutators.getSize() - 1; ++i)
  207. {
  208. if(m_mutators[i].m_name == *begin)
  209. {
  210. ANKI_PP_ERROR_MALFORMED_MSG("Duplicate mutator");
  211. }
  212. }
  213. if(begin->getLength() > MAX_SHADER_BINARY_NAME_LENGTH)
  214. {
  215. ANKI_PP_ERROR_MALFORMED_MSG("Too big name");
  216. }
  217. mutator.m_name.create(begin->toCString());
  218. ++begin;
  219. }
  220. // Values
  221. {
  222. // Gather them
  223. for(; begin < end; ++begin)
  224. {
  225. MutatorValue value = 0;
  226. if(tokenIsComment(begin->toCString()))
  227. {
  228. break;
  229. }
  230. if(begin->toNumber(value))
  231. {
  232. ANKI_PP_ERROR_MALFORMED();
  233. }
  234. mutator.m_values.emplaceBack(value);
  235. }
  236. // Check for correct count
  237. if(mutator.m_values.getSize() < 2)
  238. {
  239. ANKI_PP_ERROR_MALFORMED_MSG("Mutator with less that 2 values doesn't make sense");
  240. }
  241. std::sort(mutator.m_values.getBegin(), mutator.m_values.getEnd());
  242. // Check for duplicates
  243. for(U32 i = 1; i < mutator.m_values.getSize(); ++i)
  244. {
  245. if(mutator.m_values[i - 1] == mutator.m_values[i])
  246. {
  247. ANKI_PP_ERROR_MALFORMED_MSG("Same value appeared more than once");
  248. }
  249. }
  250. }
  251. return Error::NONE;
  252. }
  253. Error ShaderProgramParser::parsePragmaRewriteMutation(
  254. const StringAuto* begin, const StringAuto* end, CString line, CString fname)
  255. {
  256. ANKI_ASSERT(begin && end);
  257. // Some basic sanity checks
  258. const U tokenCount = end - begin;
  259. constexpr U minTokenCount = 2 + 1 + 2; // Mutator + value + "to" + mutator + value
  260. if(tokenCount < minTokenCount)
  261. {
  262. ANKI_PP_ERROR_MALFORMED();
  263. }
  264. MutationRewrite& rewrite = *m_mutationRewrites.emplaceBack(m_alloc);
  265. Bool servingFrom = true;
  266. do
  267. {
  268. if(*begin == "to")
  269. {
  270. if(servingFrom == false)
  271. {
  272. ANKI_PP_ERROR_MALFORMED();
  273. }
  274. servingFrom = false;
  275. }
  276. else
  277. {
  278. // Mutator & value
  279. // Get mutator and value
  280. const CString mutatorName = *begin;
  281. ++begin;
  282. if(begin == end)
  283. {
  284. ANKI_PP_ERROR_MALFORMED();
  285. }
  286. const CString valueStr = *begin;
  287. MutatorValue value;
  288. if(valueStr.toNumber(value))
  289. {
  290. ANKI_PP_ERROR_MALFORMED_MSG("Malformed value");
  291. }
  292. // Get or create new record
  293. if(servingFrom)
  294. {
  295. MutationRewrite::Record& rec = *rewrite.m_records.emplaceBack();
  296. for(U32 i = 0; i < m_mutators.getSize(); ++i)
  297. {
  298. if(m_mutators[i].getName() == mutatorName)
  299. {
  300. rec.m_mutatorIndex = i;
  301. break;
  302. }
  303. }
  304. if(rec.m_mutatorIndex == MAX_U32)
  305. {
  306. ANKI_PP_ERROR_MALFORMED_MSG("Mutator not found");
  307. }
  308. if(!mutatorHasValue(m_mutators[rec.m_mutatorIndex], value))
  309. {
  310. ANKI_PP_ERROR_MALFORMED_MSG("Incorect value for mutator");
  311. }
  312. rec.m_valueFrom = value;
  313. }
  314. else
  315. {
  316. Bool found = false;
  317. for(MutationRewrite::Record& rec : rewrite.m_records)
  318. {
  319. if(m_mutators[rec.m_mutatorIndex].m_name == mutatorName)
  320. {
  321. if(!mutatorHasValue(m_mutators[rec.m_mutatorIndex], value))
  322. {
  323. ANKI_PP_ERROR_MALFORMED_MSG("Incorect value for mutator");
  324. }
  325. rec.m_valueTo = value;
  326. found = true;
  327. break;
  328. }
  329. }
  330. if(!found)
  331. {
  332. ANKI_PP_ERROR_MALFORMED();
  333. }
  334. }
  335. }
  336. ++begin;
  337. } while(begin < end && !tokenIsComment(*begin));
  338. // Sort for some later cross checking
  339. std::sort(rewrite.m_records.getBegin(),
  340. rewrite.m_records.getEnd(),
  341. [](const MutationRewrite::Record& a, const MutationRewrite::Record& b) {
  342. return a.m_mutatorIndex < b.m_mutatorIndex;
  343. });
  344. // More cross checking
  345. for(U32 i = 1; i < rewrite.m_records.getSize(); ++i)
  346. {
  347. if(rewrite.m_records[i - 1].m_mutatorIndex == rewrite.m_records[i].m_mutatorIndex)
  348. {
  349. ANKI_PP_ERROR_MALFORMED_MSG("Mutator appeared more than once");
  350. }
  351. }
  352. for(U32 i = 0; i < m_mutationRewrites.getSize() - 1; ++i)
  353. {
  354. const MutationRewrite& other = m_mutationRewrites[i];
  355. if(other.m_records.getSize() != rewrite.m_records.getSize())
  356. {
  357. continue;
  358. }
  359. Bool same = true;
  360. for(U32 j = 0; j < rewrite.m_records.getSize(); ++j)
  361. {
  362. if(rewrite.m_records[j] != other.m_records[j])
  363. {
  364. same = false;
  365. break;
  366. }
  367. }
  368. if(same)
  369. {
  370. ANKI_PP_ERROR_MALFORMED_MSG("Mutation already exists");
  371. }
  372. }
  373. return Error::NONE;
  374. }
  375. Error ShaderProgramParser::parseInclude(
  376. const StringAuto* begin, const StringAuto* end, CString line, CString fname, U32 depth)
  377. {
  378. // Gather the path
  379. StringAuto path(m_alloc);
  380. for(; begin < end; ++begin)
  381. {
  382. path.append(*begin);
  383. }
  384. if(path.isEmpty())
  385. {
  386. ANKI_PP_ERROR_MALFORMED();
  387. }
  388. // Check
  389. const char firstChar = path[0];
  390. const char lastChar = path[path.getLength() - 1];
  391. if((firstChar == '\"' && lastChar == '\"') || (firstChar == '<' && lastChar == '>'))
  392. {
  393. StringAuto fname2(m_alloc);
  394. fname2.create(path.begin() + 1, path.begin() + path.getLength() - 1);
  395. if(parseFile(fname2, depth + 1))
  396. {
  397. ANKI_PP_ERROR_MALFORMED_MSG("Error parsing include. See previous errors");
  398. }
  399. }
  400. else
  401. {
  402. ANKI_PP_ERROR_MALFORMED();
  403. }
  404. return Error::NONE;
  405. }
  406. Error ShaderProgramParser::parseLine(CString line, CString fname, Bool& foundPragmaOnce, U32 depth)
  407. {
  408. // Tokenize
  409. DynamicArrayAuto<StringAuto> tokens(m_alloc);
  410. tokenizeLine(line, tokens);
  411. ANKI_ASSERT(tokens.getSize() > 0);
  412. const StringAuto* token = tokens.getBegin();
  413. const StringAuto* end = tokens.getEnd();
  414. // Skip the hash
  415. Bool foundAloneHash = false;
  416. if(*token == "#")
  417. {
  418. ++token;
  419. foundAloneHash = true;
  420. }
  421. if((token < end) && ((foundAloneHash && *token == "include") || *token == "#include"))
  422. {
  423. // We _must_ have an #include
  424. ANKI_CHECK(parseInclude(token + 1, end, line, fname, depth));
  425. }
  426. else if((token < end) && ((foundAloneHash && *token == "pragma") || *token == "#pragma"))
  427. {
  428. // We may have a #pragma once or a #pragma anki or something else
  429. ++token;
  430. if(*token == "once")
  431. {
  432. // Pragma once
  433. if(foundPragmaOnce)
  434. {
  435. ANKI_PP_ERROR_MALFORMED_MSG("Can't have more than one #pragma once per file");
  436. }
  437. if(token + 1 != end)
  438. {
  439. ANKI_PP_ERROR_MALFORMED();
  440. }
  441. // Add the guard unique for this file
  442. foundPragmaOnce = true;
  443. const U64 hash = fname.computeHash();
  444. m_codeLines.pushBackSprintf("#ifndef _ANKI_INCL_GUARD_%llu\n"
  445. "#define _ANKI_INCL_GUARD_%llu",
  446. hash,
  447. hash);
  448. }
  449. else if(*token == "anki")
  450. {
  451. // Must be a #pragma anki
  452. ++token;
  453. if(*token == "mutator")
  454. {
  455. ANKI_CHECK(parsePragmaMutator(token + 1, end, line, fname));
  456. }
  457. else if(*token == "start")
  458. {
  459. ANKI_CHECK(parsePragmaStart(token + 1, end, line, fname));
  460. }
  461. else if(*token == "end")
  462. {
  463. ANKI_CHECK(parsePragmaEnd(token + 1, end, line, fname));
  464. }
  465. else if(*token == "rewrite_mutation")
  466. {
  467. ANKI_CHECK(parsePragmaRewriteMutation(token + 1, end, line, fname));
  468. }
  469. else
  470. {
  471. ANKI_PP_ERROR_MALFORMED();
  472. }
  473. }
  474. else
  475. {
  476. // Some other pragma
  477. ANKI_SHADER_COMPILER_LOGW("Ignoring: %s", line.cstr());
  478. m_codeLines.pushBack(line);
  479. }
  480. }
  481. else
  482. {
  483. // Ignore
  484. m_codeLines.pushBack(line);
  485. }
  486. return Error::NONE;
  487. }
  488. Error ShaderProgramParser::parseFile(CString fname, U32 depth)
  489. {
  490. // First check the depth
  491. if(depth > MAX_INCLUDE_DEPTH)
  492. {
  493. ANKI_SHADER_COMPILER_LOGE("The include depth is too high. Probably circular includance");
  494. }
  495. Bool foundPragmaOnce = false;
  496. // Load file in lines
  497. StringAuto txt(m_alloc);
  498. ANKI_CHECK(m_fsystem->readAllText(fname, txt));
  499. StringListAuto lines(m_alloc);
  500. lines.splitString(txt.toCString(), '\n');
  501. if(lines.getSize() < 1)
  502. {
  503. ANKI_SHADER_COMPILER_LOGE("Source is empty");
  504. }
  505. // Parse lines
  506. for(const String& line : lines)
  507. {
  508. if(line.find("pragma") != CString::NPOS || line.find("include") != CString::NPOS)
  509. {
  510. // Possibly a preprocessor directive we care
  511. ANKI_CHECK(parseLine(line.toCString(), fname, foundPragmaOnce, depth));
  512. }
  513. else
  514. {
  515. // Just append the line
  516. m_codeLines.pushBack(line.toCString());
  517. }
  518. }
  519. if(foundPragmaOnce)
  520. {
  521. // Append the guard
  522. m_codeLines.pushBack("#endif // Include guard");
  523. }
  524. if(m_insideShader)
  525. {
  526. ANKI_SHADER_COMPILER_LOGE("Forgot a \"pragma anki end\"");
  527. return Error::USER_DATA;
  528. }
  529. return Error::NONE;
  530. }
  531. Error ShaderProgramParser::parse()
  532. {
  533. ANKI_ASSERT(!m_fname.isEmpty());
  534. ANKI_ASSERT(m_codeLines.isEmpty());
  535. const CString fname = m_fname;
  536. // Parse recursively
  537. ANKI_CHECK(parseFile(fname, 0));
  538. // Checks
  539. {
  540. if(!!(m_shaderTypes & ShaderTypeBit::COMPUTE))
  541. {
  542. if(m_shaderTypes != ShaderTypeBit::COMPUTE)
  543. {
  544. ANKI_SHADER_COMPILER_LOGE("Can't combine compute shader with other types of shaders");
  545. return Error::USER_DATA;
  546. }
  547. }
  548. else
  549. {
  550. if(!(m_shaderTypes & ShaderTypeBit::VERTEX))
  551. {
  552. ANKI_SHADER_COMPILER_LOGE("Missing vertex shader");
  553. return Error::USER_DATA;
  554. }
  555. if(!(m_shaderTypes & ShaderTypeBit::FRAGMENT))
  556. {
  557. ANKI_SHADER_COMPILER_LOGE("Missing fragment shader");
  558. return Error::USER_DATA;
  559. }
  560. }
  561. }
  562. // Create the code lines
  563. if(m_codeLines.getSize())
  564. {
  565. m_codeLines.join("\n", m_codeSource);
  566. m_codeLines.destroy();
  567. }
  568. return Error::NONE;
  569. }
  570. Error ShaderProgramParser::generateVariant(
  571. ConstWeakArray<MutatorValue> mutation, ShaderProgramParserVariant& variant) const
  572. {
  573. // Sanity checks
  574. ANKI_ASSERT(m_codeSource.getLength() > 0);
  575. ANKI_ASSERT(mutation.getSize() == m_mutators.getSize());
  576. for(U32 i = 0; i < mutation.getSize(); ++i)
  577. {
  578. ANKI_ASSERT(mutatorHasValue(m_mutators[i], mutation[i]) && "Value not found");
  579. }
  580. // Init variant
  581. ::new(&variant) ShaderProgramParserVariant();
  582. variant.m_alloc = m_alloc;
  583. // Create the mutator defines
  584. StringAuto mutatorDefines(m_alloc);
  585. for(U32 i = 0; i < mutation.getSize(); ++i)
  586. {
  587. mutatorDefines.append(StringAuto(m_alloc).sprintf("#define %s %d\n", m_mutators[i].m_name.cstr(), mutation[i]));
  588. }
  589. // Create the header
  590. StringAuto header(m_alloc);
  591. header.sprintf(SHADER_HEADER,
  592. m_backendMinor,
  593. m_backendMajor,
  594. GPU_VENDOR_STR[m_gpuVendor].cstr(),
  595. m_bindlessLimits.m_bindlessTextureCount,
  596. m_bindlessLimits.m_bindlessImageCount);
  597. // Generate souce per stage
  598. for(ShaderType shaderType = ShaderType::FIRST; shaderType < ShaderType::COUNT; ++shaderType)
  599. {
  600. if(!((1u << ShaderTypeBit(shaderType)) & m_shaderTypes))
  601. {
  602. continue;
  603. }
  604. // Create the final source without the bindings
  605. StringAuto finalSource(m_alloc);
  606. finalSource.append(header);
  607. finalSource.append(mutatorDefines);
  608. finalSource.append(StringAuto(m_alloc).sprintf("#define ANKI_%s 1\n", SHADER_STAGE_NAMES[shaderType].cstr()));
  609. finalSource.append(m_codeSource);
  610. // Move the source
  611. variant.m_sources[shaderType] = std::move(finalSource);
  612. }
  613. return Error::NONE;
  614. }
  615. Bool ShaderProgramParser::rewriteMutation(WeakArray<MutatorValue> mutation) const
  616. {
  617. // Checks
  618. ANKI_ASSERT(mutation.getSize() == m_mutators.getSize());
  619. for(U32 i = 0; i < mutation.getSize(); ++i)
  620. {
  621. ANKI_ASSERT(mutatorHasValue(m_mutators[i], mutation[i]));
  622. }
  623. // Early exit
  624. if(mutation.getSize() == 0)
  625. {
  626. return false;
  627. }
  628. // Find if mutation exists
  629. for(const MutationRewrite& rewrite : m_mutationRewrites)
  630. {
  631. Bool found = true;
  632. for(U32 i = 0; i < rewrite.m_records.getSize(); ++i)
  633. {
  634. if(rewrite.m_records[i].m_valueFrom != mutation[rewrite.m_records[i].m_mutatorIndex])
  635. {
  636. found = false;
  637. break;
  638. }
  639. }
  640. if(found)
  641. {
  642. // Rewrite it
  643. for(U32 i = 0; i < rewrite.m_records.getSize(); ++i)
  644. {
  645. mutation[rewrite.m_records[i].m_mutatorIndex] = rewrite.m_records[i].m_valueTo;
  646. }
  647. return true;
  648. }
  649. }
  650. return false;
  651. }
  652. Bool ShaderProgramParser::mutatorHasValue(const ShaderProgramParserMutator& mutator, MutatorValue value)
  653. {
  654. for(MutatorValue v : mutator.m_values)
  655. {
  656. if(value == v)
  657. {
  658. return true;
  659. }
  660. }
  661. return false;
  662. }
  663. } // end namespace anki