MaterialShaderProgramCreator.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. namespace anki {
  8. //==============================================================================
  9. MaterialShaderProgramCreator::MaterialShaderProgramCreator(
  10. const boost::property_tree::ptree& pt)
  11. {
  12. parseShaderProgramTag(pt);
  13. }
  14. //==============================================================================
  15. MaterialShaderProgramCreator::~MaterialShaderProgramCreator()
  16. {}
  17. //==============================================================================
  18. void MaterialShaderProgramCreator::parseShaderProgramTag(
  19. const boost::property_tree::ptree& pt)
  20. {
  21. using namespace boost::property_tree;
  22. BOOST_FOREACH(const ptree::value_type& v, pt)
  23. {
  24. if(v.first != "shader")
  25. {
  26. throw ANKI_EXCEPTION("Expected \"shader\" tag and not: " +
  27. v.first);
  28. }
  29. parseShaderTag(v.second);
  30. }
  31. source = srcLines.join("\n");
  32. //std::cout << source << std::endl;
  33. }
  34. //==============================================================================
  35. void MaterialShaderProgramCreator::parseShaderTag(
  36. const boost::property_tree::ptree& pt)
  37. {
  38. using namespace boost::property_tree;
  39. //
  40. // <type></type>
  41. //
  42. const std::string& type = pt.get<std::string>("type");
  43. srcLines.push_back("#pragma anki start " + type + "Shader");
  44. //
  45. // <includes></includes>
  46. //
  47. std::vector<std::string> includeLines;
  48. const ptree& includesPt = pt.get_child("includes");
  49. BOOST_FOREACH(const ptree::value_type& v, includesPt)
  50. {
  51. if(v.first != "include")
  52. {
  53. throw ANKI_EXCEPTION("Expected \"include\" tag and not: " +
  54. v.first);
  55. }
  56. const std::string& fname = v.second.data();
  57. includeLines.push_back(std::string("#pragma anki include \"") +
  58. fname + "\"");
  59. }
  60. //std::sort(includeLines.begin(), includeLines.end(), compareStrings);
  61. srcLines.insert(srcLines.end(), includeLines.begin(), includeLines.end());
  62. //
  63. // <inputs></inputs>
  64. //
  65. boost::optional<const ptree&> insPt = pt.get_child_optional("inputs");
  66. if(insPt)
  67. {
  68. // Store the source of the uniform vars
  69. std::vector<std::string> uniformsLines;
  70. BOOST_FOREACH(const ptree::value_type& v, insPt.get())
  71. {
  72. if(v.first != "input")
  73. {
  74. throw ANKI_EXCEPTION("Expected \"input\" tag and not: " +
  75. v.first);
  76. }
  77. const ptree& inPt = v.second;
  78. std::string line;
  79. parseInputTag(inPt, line);
  80. uniformsLines.push_back(line);
  81. } // end for all ins
  82. srcLines.push_back("");
  83. std::sort(uniformsLines.begin(), uniformsLines.end(), compareStrings);
  84. srcLines.insert(srcLines.end(), uniformsLines.begin(),
  85. uniformsLines.end());
  86. }
  87. //
  88. // <operations></operations>
  89. //
  90. srcLines.push_back("\nvoid main()\n{");
  91. const ptree& opsPt = pt.get_child("operations");
  92. BOOST_FOREACH(const ptree::value_type& v, opsPt)
  93. {
  94. if(v.first != "operation")
  95. {
  96. throw ANKI_EXCEPTION("Expected \"operation\" tag and not: " +
  97. v.first);
  98. }
  99. const ptree& opPt = v.second;
  100. parseOperationTag(opPt);
  101. } // end for all operations
  102. srcLines.push_back("}\n");
  103. }
  104. //==============================================================================
  105. void MaterialShaderProgramCreator::parseInputTag(
  106. const boost::property_tree::ptree& pt, std::string& line)
  107. {
  108. using namespace boost::property_tree;
  109. const std::string& name = pt.get<std::string>("name");
  110. const std::string& type = pt.get<std::string>("type");
  111. line = "uniform " + type + " " + name + ";";
  112. }
  113. //==============================================================================
  114. void MaterialShaderProgramCreator::parseOperationTag(
  115. const boost::property_tree::ptree& pt)
  116. {
  117. using namespace boost::property_tree;
  118. std::stringstream line;
  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. if(retTypeOpt)
  125. {
  126. line << retTypeOpt.get() << " operationOut" << id << " = ";
  127. }
  128. // <function>functionName</function>
  129. const std::string& funcName = pt.get<std::string>("function");
  130. line << funcName << "(";
  131. // <arguments></arguments>
  132. boost::optional<const ptree&> argsPt = pt.get_child_optional("arguments");
  133. StringList argsList;
  134. if(argsPt)
  135. {
  136. // Write 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. line << argsList.join(", ");
  151. }
  152. line << ");";
  153. srcLines.push_back("\t" + line.str());
  154. }
  155. //==============================================================================
  156. bool MaterialShaderProgramCreator::compareStrings(
  157. const std::string& a, const std::string& b)
  158. {
  159. return a < b;
  160. }
  161. } // end namespace