SkSLHCodeGenerator.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*
  2. * Copyright 2016 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/sksl/SkSLHCodeGenerator.h"
  8. #include "src/sksl/SkSLParser.h"
  9. #include "src/sksl/SkSLUtil.h"
  10. #include "src/sksl/ir/SkSLEnum.h"
  11. #include "src/sksl/ir/SkSLFunctionDeclaration.h"
  12. #include "src/sksl/ir/SkSLFunctionDefinition.h"
  13. #include "src/sksl/ir/SkSLSection.h"
  14. #include "src/sksl/ir/SkSLVarDeclarations.h"
  15. #include <set>
  16. namespace SkSL {
  17. HCodeGenerator::HCodeGenerator(const Context* context, const Program* program,
  18. ErrorReporter* errors, String name, OutputStream* out)
  19. : INHERITED(program, errors, out)
  20. , fContext(*context)
  21. , fName(std::move(name))
  22. , fFullName(String::printf("Gr%s", fName.c_str()))
  23. , fSectionAndParameterHelper(*program, *errors) {}
  24. String HCodeGenerator::ParameterType(const Context& context, const Type& type,
  25. const Layout& layout) {
  26. Layout::CType ctype = ParameterCType(context, type, layout);
  27. if (ctype != Layout::CType::kDefault) {
  28. return Layout::CTypeToStr(ctype);
  29. }
  30. return type.name();
  31. }
  32. Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type,
  33. const Layout& layout) {
  34. if (layout.fCType != Layout::CType::kDefault) {
  35. return layout.fCType;
  36. }
  37. if (type.kind() == Type::kNullable_Kind) {
  38. return ParameterCType(context, type.componentType(), layout);
  39. } else if (type == *context.fFloat_Type || type == *context.fHalf_Type) {
  40. return Layout::CType::kFloat;
  41. } else if (type == *context.fInt_Type ||
  42. type == *context.fShort_Type ||
  43. type == *context.fByte_Type) {
  44. return Layout::CType::kInt32;
  45. } else if (type == *context.fFloat2_Type || type == *context.fHalf2_Type) {
  46. return Layout::CType::kSkPoint;
  47. } else if (type == *context.fInt2_Type ||
  48. type == *context.fShort2_Type ||
  49. type == *context.fByte2_Type) {
  50. return Layout::CType::kSkIPoint;
  51. } else if (type == *context.fInt4_Type ||
  52. type == *context.fShort4_Type ||
  53. type == *context.fByte4_Type) {
  54. return Layout::CType::kSkIRect;
  55. } else if (type == *context.fFloat4_Type || type == *context.fHalf4_Type) {
  56. return Layout::CType::kSkRect;
  57. } else if (type == *context.fFloat3x3_Type || type == *context.fHalf3x3_Type) {
  58. return Layout::CType::kSkMatrix;
  59. } else if (type == *context.fFloat4x4_Type || type == *context.fHalf4x4_Type) {
  60. return Layout::CType::kSkMatrix44;
  61. } else if (type.kind() == Type::kSampler_Kind) {
  62. return Layout::CType::kGrTextureProxy;
  63. } else if (type == *context.fFragmentProcessor_Type) {
  64. return Layout::CType::kGrFragmentProcessor;
  65. }
  66. return Layout::CType::kDefault;
  67. }
  68. String HCodeGenerator::FieldType(const Context& context, const Type& type,
  69. const Layout& layout) {
  70. if (type.kind() == Type::kSampler_Kind) {
  71. return "TextureSampler";
  72. } else if (type == *context.fFragmentProcessor_Type) {
  73. // we don't store fragment processors in fields, they get registered via
  74. // registerChildProcessor instead
  75. SkASSERT(false);
  76. return "<error>";
  77. }
  78. return ParameterType(context, type, layout);
  79. }
  80. String HCodeGenerator::AccessType(const Context& context, const Type& type,
  81. const Layout& layout) {
  82. static const std::set<String> primitiveTypes = { "int32_t", "float", "bool", "SkPMColor" };
  83. String fieldType = FieldType(context, type, layout);
  84. bool isPrimitive = primitiveTypes.find(fieldType) != primitiveTypes.end();
  85. if (isPrimitive) {
  86. return fieldType;
  87. } else {
  88. return String::printf("const %s&", fieldType.c_str());
  89. }
  90. }
  91. void HCodeGenerator::writef(const char* s, va_list va) {
  92. static constexpr int BUFFER_SIZE = 1024;
  93. va_list copy;
  94. va_copy(copy, va);
  95. char buffer[BUFFER_SIZE];
  96. int length = vsnprintf(buffer, BUFFER_SIZE, s, va);
  97. if (length < BUFFER_SIZE) {
  98. fOut->write(buffer, length);
  99. } else {
  100. std::unique_ptr<char[]> heap(new char[length + 1]);
  101. vsprintf(heap.get(), s, copy);
  102. fOut->write(heap.get(), length);
  103. }
  104. va_end(copy);
  105. }
  106. void HCodeGenerator::writef(const char* s, ...) {
  107. va_list va;
  108. va_start(va, s);
  109. this->writef(s, va);
  110. va_end(va);
  111. }
  112. bool HCodeGenerator::writeSection(const char* name, const char* prefix) {
  113. const Section* s = fSectionAndParameterHelper.getSection(name);
  114. if (s) {
  115. this->writef("%s%s", prefix, s->fText.c_str());
  116. return true;
  117. }
  118. return false;
  119. }
  120. void HCodeGenerator::writeExtraConstructorParams(const char* separator) {
  121. // super-simple parse, just assume the last token before a comma is the name of a parameter
  122. // (which is true as long as there are no multi-parameter template types involved). Will replace
  123. // this with something more robust if the need arises.
  124. const Section* section = fSectionAndParameterHelper.getSection(CONSTRUCTOR_PARAMS_SECTION);
  125. if (section) {
  126. const char* s = section->fText.c_str();
  127. #define BUFFER_SIZE 64
  128. char lastIdentifier[BUFFER_SIZE];
  129. int lastIdentifierLength = 0;
  130. bool foundBreak = false;
  131. while (*s) {
  132. char c = *s;
  133. ++s;
  134. if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
  135. c == '_') {
  136. if (foundBreak) {
  137. lastIdentifierLength = 0;
  138. foundBreak = false;
  139. }
  140. SkASSERT(lastIdentifierLength < BUFFER_SIZE);
  141. lastIdentifier[lastIdentifierLength] = c;
  142. ++lastIdentifierLength;
  143. } else {
  144. foundBreak = true;
  145. if (c == ',') {
  146. SkASSERT(lastIdentifierLength < BUFFER_SIZE);
  147. lastIdentifier[lastIdentifierLength] = 0;
  148. this->writef("%s%s", separator, lastIdentifier);
  149. separator = ", ";
  150. } else if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
  151. lastIdentifierLength = 0;
  152. }
  153. }
  154. }
  155. if (lastIdentifierLength) {
  156. SkASSERT(lastIdentifierLength < BUFFER_SIZE);
  157. lastIdentifier[lastIdentifierLength] = 0;
  158. this->writef("%s%s", separator, lastIdentifier);
  159. }
  160. }
  161. }
  162. void HCodeGenerator::writeMake() {
  163. const char* separator;
  164. if (!this->writeSection(MAKE_SECTION)) {
  165. this->writef(" static std::unique_ptr<GrFragmentProcessor> Make(");
  166. separator = "";
  167. for (const auto& param : fSectionAndParameterHelper.getParameters()) {
  168. this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
  169. param->fModifiers.fLayout).c_str(),
  170. String(param->fName).c_str());
  171. separator = ", ";
  172. }
  173. this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
  174. this->writef(") {\n"
  175. " return std::unique_ptr<GrFragmentProcessor>(new %s(",
  176. fFullName.c_str());
  177. separator = "";
  178. for (const auto& param : fSectionAndParameterHelper.getParameters()) {
  179. if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
  180. this->writef("%sstd::move(%s)", separator, String(param->fName).c_str());
  181. } else {
  182. this->writef("%s%s", separator, String(param->fName).c_str());
  183. }
  184. separator = ", ";
  185. }
  186. this->writeExtraConstructorParams(separator);
  187. this->writef("));\n"
  188. " }\n");
  189. }
  190. }
  191. void HCodeGenerator::failOnSection(const char* section, const char* msg) {
  192. std::vector<const Section*> s = fSectionAndParameterHelper.getSections(section);
  193. if (s.size()) {
  194. fErrors.error(s[0]->fOffset, String("@") + section + " " + msg);
  195. }
  196. }
  197. void HCodeGenerator::writeConstructor() {
  198. if (this->writeSection(CONSTRUCTOR_SECTION)) {
  199. const char* msg = "may not be present when constructor is overridden";
  200. this->failOnSection(CONSTRUCTOR_CODE_SECTION, msg);
  201. this->failOnSection(CONSTRUCTOR_PARAMS_SECTION, msg);
  202. this->failOnSection(INITIALIZERS_SECTION, msg);
  203. this->failOnSection(OPTIMIZATION_FLAGS_SECTION, msg);
  204. return;
  205. }
  206. this->writef(" %s(", fFullName.c_str());
  207. const char* separator = "";
  208. for (const auto& param : fSectionAndParameterHelper.getParameters()) {
  209. this->writef("%s%s %s", separator, ParameterType(fContext, param->fType,
  210. param->fModifiers.fLayout).c_str(),
  211. String(param->fName).c_str());
  212. separator = ", ";
  213. }
  214. this->writeSection(CONSTRUCTOR_PARAMS_SECTION, separator);
  215. this->writef(")\n"
  216. " : INHERITED(k%s_ClassID", fFullName.c_str());
  217. if (!this->writeSection(OPTIMIZATION_FLAGS_SECTION, ", (OptimizationFlags) ")) {
  218. this->writef(", kNone_OptimizationFlags");
  219. }
  220. this->writef(")");
  221. this->writeSection(INITIALIZERS_SECTION, "\n , ");
  222. const auto transforms = fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION);
  223. for (size_t i = 0; i < transforms.size(); ++i) {
  224. const Section& s = *transforms[i];
  225. String field = CoordTransformName(s.fArgument.c_str(), i);
  226. if (s.fArgument.size()) {
  227. this->writef("\n , %s(%s, %s.get())", field.c_str(), s.fText.c_str(),
  228. FieldName(s.fArgument.c_str()).c_str());
  229. }
  230. else {
  231. this->writef("\n , %s(%s)", field.c_str(), s.fText.c_str());
  232. }
  233. }
  234. for (const auto& param : fSectionAndParameterHelper.getParameters()) {
  235. String nameString(param->fName);
  236. const char* name = nameString.c_str();
  237. const Type& type = param->fType.nonnullable();
  238. if (type.kind() == Type::kSampler_Kind) {
  239. this->writef("\n , %s(std::move(%s)", FieldName(name).c_str(), name);
  240. for (const Section* s : fSectionAndParameterHelper.getSections(
  241. SAMPLER_PARAMS_SECTION)) {
  242. if (s->fArgument == name) {
  243. this->writef(", %s", s->fText.c_str());
  244. }
  245. }
  246. this->writef(")");
  247. } else if (type == *fContext.fFragmentProcessor_Type) {
  248. // do nothing
  249. } else {
  250. this->writef("\n , %s(%s)", FieldName(name).c_str(), name);
  251. }
  252. }
  253. this->writef(" {\n");
  254. this->writeSection(CONSTRUCTOR_CODE_SECTION);
  255. int samplerCount = 0;
  256. for (const auto& param : fSectionAndParameterHelper.getParameters()) {
  257. if (param->fType.kind() == Type::kSampler_Kind) {
  258. ++samplerCount;
  259. } else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
  260. if (param->fType.kind() == Type::kNullable_Kind) {
  261. this->writef(" if (%s) {\n", String(param->fName).c_str());
  262. } else {
  263. this->writef(" SkASSERT(%s);", String(param->fName).c_str());
  264. }
  265. this->writef(" %s_index = this->numChildProcessors();",
  266. FieldName(String(param->fName).c_str()).c_str());
  267. this->writef(" this->registerChildProcessor(std::move(%s));",
  268. String(param->fName).c_str());
  269. if (param->fType.kind() == Type::kNullable_Kind) {
  270. this->writef(" }");
  271. }
  272. }
  273. }
  274. if (samplerCount) {
  275. this->writef(" this->setTextureSamplerCnt(%d);", samplerCount);
  276. }
  277. for (size_t i = 0; i < transforms.size(); ++i) {
  278. const Section& s = *transforms[i];
  279. String field = CoordTransformName(s.fArgument.c_str(), i);
  280. this->writef(" this->addCoordTransform(&%s);\n", field.c_str());
  281. }
  282. this->writef(" }\n");
  283. }
  284. void HCodeGenerator::writeFields() {
  285. this->writeSection(FIELDS_SECTION);
  286. const auto transforms = fSectionAndParameterHelper.getSections(COORD_TRANSFORM_SECTION);
  287. for (size_t i = 0; i < transforms.size(); ++i) {
  288. const Section& s = *transforms[i];
  289. this->writef(" GrCoordTransform %s;\n",
  290. CoordTransformName(s.fArgument.c_str(), i).c_str());
  291. }
  292. for (const auto& param : fSectionAndParameterHelper.getParameters()) {
  293. String name = FieldName(String(param->fName).c_str());
  294. if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
  295. this->writef(" int %s_index = -1;\n", name.c_str());
  296. } else {
  297. this->writef(" %s %s;\n", FieldType(fContext, param->fType,
  298. param->fModifiers.fLayout).c_str(),
  299. name.c_str());
  300. }
  301. }
  302. }
  303. String HCodeGenerator::GetHeader(const Program& program, ErrorReporter& errors) {
  304. SymbolTable types(&errors);
  305. Parser parser(program.fSource->c_str(), program.fSource->length(), types, errors);
  306. for (;;) {
  307. Token header = parser.nextRawToken();
  308. switch (header.fKind) {
  309. case Token::WHITESPACE:
  310. break;
  311. case Token::BLOCK_COMMENT:
  312. return String(program.fSource->c_str() + header.fOffset, header.fLength);
  313. default:
  314. return "";
  315. }
  316. }
  317. }
  318. bool HCodeGenerator::generateCode() {
  319. this->writef("%s\n", GetHeader(fProgram, fErrors).c_str());
  320. this->writef(kFragmentProcessorHeader, fFullName.c_str());
  321. this->writef("#ifndef %s_DEFINED\n"
  322. "#define %s_DEFINED\n",
  323. fFullName.c_str(),
  324. fFullName.c_str());
  325. this->writef("#include \"include/core/SkTypes.h\"\n");
  326. this->writeSection(HEADER_SECTION);
  327. this->writef("\n"
  328. "#include \"src/gpu/GrCoordTransform.h\"\n"
  329. "#include \"src/gpu/GrFragmentProcessor.h\"\n");
  330. this->writef("class %s : public GrFragmentProcessor {\n"
  331. "public:\n",
  332. fFullName.c_str());
  333. for (const auto& p : fProgram) {
  334. if (ProgramElement::kEnum_Kind == p.fKind && !((Enum&) p).fBuiltin) {
  335. this->writef("%s\n", p.description().c_str());
  336. }
  337. }
  338. this->writeSection(CLASS_SECTION);
  339. this->writeMake();
  340. this->writef(" %s(const %s& src);\n"
  341. " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
  342. " const char* name() const override { return \"%s\"; }\n",
  343. fFullName.c_str(), fFullName.c_str(), fName.c_str());
  344. this->writeFields();
  345. this->writef("private:\n");
  346. this->writeConstructor();
  347. this->writef(" GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
  348. " void onGetGLSLProcessorKey(const GrShaderCaps&,"
  349. "GrProcessorKeyBuilder*) const override;\n"
  350. " bool onIsEqual(const GrFragmentProcessor&) const override;\n");
  351. for (const auto& param : fSectionAndParameterHelper.getParameters()) {
  352. if (param->fType.kind() == Type::kSampler_Kind) {
  353. this->writef(" const TextureSampler& onTextureSampler(int) const override;");
  354. break;
  355. }
  356. }
  357. this->writef(" GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n");
  358. this->writef(" typedef GrFragmentProcessor INHERITED;\n"
  359. "};\n");
  360. this->writeSection(HEADER_END_SECTION);
  361. this->writef("#endif\n");
  362. return 0 == fErrors.errorCount();
  363. }
  364. } // namespace