MaterialShaderProgramCreator.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #include "anki/resource/MaterialShaderProgramCreator.h"
  2. #include "anki/util/Assert.h"
  3. #include "anki/util/Exception.h"
  4. #include <boost/foreach.hpp>
  5. #include <boost/property_tree/ptree.hpp>
  6. #include <boost/lexical_cast.hpp>
  7. #include <boost/regex.hpp>
  8. namespace anki {
  9. //==============================================================================
  10. MaterialShaderProgramCreator::MaterialShaderProgramCreator(
  11. const boost::property_tree::ptree& pt)
  12. {
  13. parseShaderProgramTag(pt);
  14. }
  15. //==============================================================================
  16. MaterialShaderProgramCreator::~MaterialShaderProgramCreator()
  17. {}
  18. //==============================================================================
  19. void MaterialShaderProgramCreator::parseShaderProgramTag(
  20. const boost::property_tree::ptree& pt)
  21. {
  22. using namespace boost::property_tree;
  23. BOOST_FOREACH(const ptree::value_type& v, pt)
  24. {
  25. if(v.first != "shader")
  26. {
  27. throw ANKI_EXCEPTION("Expected \"shader\" tag and not: " +
  28. v.first);
  29. }
  30. parseShaderTag(v.second);
  31. }
  32. source = srcLines.join("\n");
  33. //std::cout << source << std::endl;
  34. }
  35. //==============================================================================
  36. void MaterialShaderProgramCreator::parseShaderTag(
  37. const boost::property_tree::ptree& pt)
  38. {
  39. using namespace boost::property_tree;
  40. //
  41. // <type></type>
  42. //
  43. const std::string& type = pt.get<std::string>("type");
  44. srcLines.push_back("#pragma anki start " + type + "Shader");
  45. //
  46. // <includes></includes>
  47. //
  48. std::vector<std::string> includeLines;
  49. const ptree& includesPt = pt.get_child("includes");
  50. BOOST_FOREACH(const ptree::value_type& v, includesPt)
  51. {
  52. if(v.first != "include")
  53. {
  54. throw ANKI_EXCEPTION("Expected \"include\" tag and not: " +
  55. v.first);
  56. }
  57. const std::string& fname = v.second.data();
  58. includeLines.push_back(std::string("#pragma anki include \"") +
  59. fname + "\"");
  60. }
  61. //std::sort(includeLines.begin(), includeLines.end(), compareStrings);
  62. srcLines.insert(srcLines.end(), includeLines.begin(), includeLines.end());
  63. //
  64. // <inputs></inputs>
  65. //
  66. boost::optional<const ptree&> insPt = pt.get_child_optional("inputs");
  67. if(insPt)
  68. {
  69. // Store the source of the uniform vars
  70. std::vector<std::string> uniformsLines;
  71. BOOST_FOREACH(const ptree::value_type& v, insPt.get())
  72. {
  73. if(v.first != "input")
  74. {
  75. throw ANKI_EXCEPTION("Expected \"input\" tag and not: " +
  76. v.first);
  77. }
  78. const ptree& inPt = v.second;
  79. std::string line;
  80. parseInputTag(inPt, line);
  81. uniformsLines.push_back(line);
  82. } // end for all ins
  83. srcLines.push_back("");
  84. std::sort(uniformsLines.begin(), uniformsLines.end(), compareStrings);
  85. srcLines.insert(srcLines.end(), uniformsLines.begin(),
  86. uniformsLines.end());
  87. }
  88. //
  89. // <operations></operations>
  90. //
  91. srcLines.push_back("\nvoid main()\n{");
  92. const ptree& opsPt = pt.get_child("operations");
  93. BOOST_FOREACH(const ptree::value_type& v, opsPt)
  94. {
  95. if(v.first != "operation")
  96. {
  97. throw ANKI_EXCEPTION("Expected \"operation\" tag and not: " +
  98. v.first);
  99. }
  100. const ptree& opPt = v.second;
  101. parseOperationTag(opPt);
  102. } // end for all operations
  103. srcLines.push_back("}\n");
  104. }
  105. //==============================================================================
  106. void MaterialShaderProgramCreator::parseInputTag(
  107. const boost::property_tree::ptree& pt, std::string& line)
  108. {
  109. using namespace boost::property_tree;
  110. const std::string& name = pt.get<std::string>("name");
  111. const std::string& type = pt.get<std::string>("type");
  112. line = "uniform " + type + " " + name + ";";
  113. }
  114. //==============================================================================
  115. void MaterialShaderProgramCreator::parseOperationTag(
  116. const boost::property_tree::ptree& pt)
  117. {
  118. using namespace boost::property_tree;
  119. // <id></id>
  120. int id = pt.get<int>("id");
  121. // <returnType></returnType>
  122. boost::optional<std::string> retTypeOpt =
  123. pt.get_optional<std::string>("returnType");
  124. std::string operationOut;
  125. if(retTypeOpt)
  126. {
  127. operationOut = "operationOut" + boost::lexical_cast<std::string>(id);
  128. }
  129. // <function>functionName</function>
  130. const std::string& funcName = pt.get<std::string>("function");
  131. // <arguments></arguments>
  132. boost::optional<const ptree&> argsPt = pt.get_child_optional("arguments");
  133. StringList argsList;
  134. if(argsPt)
  135. {
  136. // Get all arguments
  137. ptree::const_iterator it = argsPt.get().begin();
  138. for(; it != argsPt.get().end(); ++it)
  139. {
  140. const ptree::value_type& v = *it;
  141. if(v.first != "argument")
  142. {
  143. throw ANKI_EXCEPTION("Operation " +
  144. boost::lexical_cast<std::string>(id) +
  145. ": Expected \"argument\" tag and not: " + v.first);
  146. }
  147. const std::string& argName = v.second.data();
  148. argsList.push_back(argName);
  149. }
  150. }
  151. // Now write everything
  152. std::stringstream line;
  153. line << "#if defined(" << funcName << "_DEFINED)";
  154. boost::regex expr("^operationOut[0-9]*$");
  155. BOOST_FOREACH(const std::string& arg, argsList)
  156. {
  157. if(boost::regex_match(arg, expr))
  158. {
  159. line << " && defined(" << arg << "_DEFINED)";
  160. }
  161. }
  162. line << "\n";
  163. if(retTypeOpt)
  164. {
  165. line << "#\tdefine " << operationOut << "_DEFINED\n";
  166. line << '\t' << retTypeOpt.get() << " " << operationOut << " = ";
  167. }
  168. else
  169. {
  170. line << '\t';
  171. }
  172. line << funcName << "(";
  173. line << argsList.join(", ");
  174. line << ");\n";
  175. line << "#endif";
  176. // Done
  177. srcLines.push_back(line.str());
  178. }
  179. //==============================================================================
  180. bool MaterialShaderProgramCreator::compareStrings(
  181. const std::string& a, const std::string& b)
  182. {
  183. return a < b;
  184. }
  185. } // end namespace