GrGLSLShaderBuilder.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright 2014 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/gpu/glsl/GrGLSLShaderBuilder.h"
  8. #include "src/gpu/GrShaderCaps.h"
  9. #include "src/gpu/GrShaderVar.h"
  10. #include "src/gpu/GrSwizzle.h"
  11. #include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
  12. #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
  13. GrGLSLShaderBuilder::GrGLSLShaderBuilder(GrGLSLProgramBuilder* program)
  14. : fProgramBuilder(program)
  15. , fInputs(GrGLSLProgramBuilder::kVarsPerBlock)
  16. , fOutputs(GrGLSLProgramBuilder::kVarsPerBlock)
  17. , fFeaturesAddedMask(0)
  18. , fCodeIndex(kCode)
  19. , fFinalized(false) {
  20. // We push back some dummy pointers which will later become our header
  21. for (int i = 0; i <= kCode; i++) {
  22. fShaderStrings.push_back();
  23. }
  24. this->main() = "void main() {";
  25. }
  26. void GrGLSLShaderBuilder::declAppend(const GrShaderVar& var) {
  27. SkString tempDecl;
  28. var.appendDecl(fProgramBuilder->shaderCaps(), &tempDecl);
  29. this->codeAppendf("%s;", tempDecl.c_str());
  30. }
  31. void GrGLSLShaderBuilder::declareGlobal(const GrShaderVar& v) {
  32. v.appendDecl(this->getProgramBuilder()->shaderCaps(), &this->definitions());
  33. this->definitions().append(";");
  34. }
  35. void GrGLSLShaderBuilder::emitFunction(GrSLType returnType,
  36. const char* name,
  37. int argCnt,
  38. const GrShaderVar* args,
  39. const char* body,
  40. SkString* outName) {
  41. this->functions().append(GrGLSLTypeString(returnType));
  42. fProgramBuilder->nameVariable(outName, '\0', name);
  43. this->functions().appendf(" %s", outName->c_str());
  44. this->functions().append("(");
  45. for (int i = 0; i < argCnt; ++i) {
  46. args[i].appendDecl(fProgramBuilder->shaderCaps(), &this->functions());
  47. if (i < argCnt - 1) {
  48. this->functions().append(", ");
  49. }
  50. }
  51. this->functions().append(") {\n");
  52. this->functions().append(body);
  53. this->functions().append("}\n\n");
  54. }
  55. static inline void append_texture_swizzle(SkString* out, GrSwizzle swizzle) {
  56. if (swizzle != GrSwizzle::RGBA()) {
  57. out->appendf(".%s", swizzle.c_str());
  58. }
  59. }
  60. void GrGLSLShaderBuilder::appendTextureLookup(SkString* out,
  61. SamplerHandle samplerHandle,
  62. const char* coordName,
  63. GrSLType varyingType) const {
  64. const char* sampler = fProgramBuilder->samplerVariable(samplerHandle);
  65. out->appendf("texture(%s, %s)", sampler, coordName);
  66. append_texture_swizzle(out, fProgramBuilder->samplerSwizzle(samplerHandle));
  67. }
  68. void GrGLSLShaderBuilder::appendTextureLookup(SamplerHandle samplerHandle,
  69. const char* coordName,
  70. GrSLType varyingType,
  71. GrGLSLColorSpaceXformHelper* colorXformHelper) {
  72. SkString lookup;
  73. this->appendTextureLookup(&lookup, samplerHandle, coordName, varyingType);
  74. this->appendColorGamutXform(lookup.c_str(), colorXformHelper);
  75. }
  76. void GrGLSLShaderBuilder::appendTextureLookupAndModulate(
  77. const char* modulation,
  78. SamplerHandle samplerHandle,
  79. const char* coordName,
  80. GrSLType varyingType,
  81. GrGLSLColorSpaceXformHelper* colorXformHelper) {
  82. SkString lookup;
  83. this->appendTextureLookup(&lookup, samplerHandle, coordName, varyingType);
  84. this->appendColorGamutXform(lookup.c_str(), colorXformHelper);
  85. if (modulation) {
  86. this->codeAppendf(" * %s", modulation);
  87. }
  88. }
  89. void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
  90. const char* srcColor,
  91. GrGLSLColorSpaceXformHelper* colorXformHelper) {
  92. if (!colorXformHelper || colorXformHelper->isNoop()) {
  93. *out = srcColor;
  94. return;
  95. }
  96. GrGLSLUniformHandler* uniformHandler = fProgramBuilder->uniformHandler();
  97. // We define up to three helper functions, to keep things clearer. One for the source transfer
  98. // function, one for the (inverse) destination transfer function, and one for the gamut xform.
  99. // Any combination of these may be present, although some configurations are much more likely.
  100. auto emitTFFunc = [=](const char* name, GrGLSLProgramDataManager::UniformHandle uniform) {
  101. const GrShaderVar gTFArgs[] = { GrShaderVar("x", kHalf_GrSLType) };
  102. const char* coeffs = uniformHandler->getUniformCStr(uniform);
  103. SkString body;
  104. // Temporaries to make evaluation line readable
  105. body.appendf("half G = %s[0];", coeffs);
  106. body.appendf("half A = %s[1];", coeffs);
  107. body.appendf("half B = %s[2];", coeffs);
  108. body.appendf("half C = %s[3];", coeffs);
  109. body.appendf("half D = %s[4];", coeffs);
  110. body.appendf("half E = %s[5];", coeffs);
  111. body.appendf("half F = %s[6];", coeffs);
  112. body.append("half s = sign(x);");
  113. body.append("x = abs(x);");
  114. body.appendf("return s * ((x < D) ? (C * x) + F : pow(A * x + B, G) + E);");
  115. SkString funcName;
  116. this->emitFunction(kHalf_GrSLType, name, SK_ARRAY_COUNT(gTFArgs), gTFArgs, body.c_str(),
  117. &funcName);
  118. return funcName;
  119. };
  120. SkString srcTFFuncName;
  121. if (colorXformHelper->applySrcTF()) {
  122. srcTFFuncName = emitTFFunc("src_tf", colorXformHelper->srcTFUniform());
  123. }
  124. SkString dstTFFuncName;
  125. if (colorXformHelper->applyDstTF()) {
  126. dstTFFuncName = emitTFFunc("dst_tf", colorXformHelper->dstTFUniform());
  127. }
  128. SkString gamutXformFuncName;
  129. if (colorXformHelper->applyGamutXform()) {
  130. const GrShaderVar gGamutXformArgs[] = { GrShaderVar("color", kHalf4_GrSLType) };
  131. const char* xform = uniformHandler->getUniformCStr(colorXformHelper->gamutXformUniform());
  132. SkString body;
  133. body.appendf("color.rgb = (%s * color.rgb);", xform);
  134. body.append("return color;");
  135. this->emitFunction(kHalf4_GrSLType, "gamut_xform", SK_ARRAY_COUNT(gGamutXformArgs),
  136. gGamutXformArgs, body.c_str(), &gamutXformFuncName);
  137. }
  138. // Now define a wrapper function that applies all the intermediate steps
  139. {
  140. const GrShaderVar gColorXformArgs[] = { GrShaderVar("color", kHalf4_GrSLType) };
  141. SkString body;
  142. if (colorXformHelper->applyUnpremul()) {
  143. body.append("half nonZeroAlpha = max(color.a, 0.0001);");
  144. body.append("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
  145. }
  146. if (colorXformHelper->applySrcTF()) {
  147. body.appendf("color.r = %s(color.r);", srcTFFuncName.c_str());
  148. body.appendf("color.g = %s(color.g);", srcTFFuncName.c_str());
  149. body.appendf("color.b = %s(color.b);", srcTFFuncName.c_str());
  150. }
  151. if (colorXformHelper->applyGamutXform()) {
  152. body.appendf("color = %s(color);", gamutXformFuncName.c_str());
  153. }
  154. if (colorXformHelper->applyDstTF()) {
  155. body.appendf("color.r = %s(color.r);", dstTFFuncName.c_str());
  156. body.appendf("color.g = %s(color.g);", dstTFFuncName.c_str());
  157. body.appendf("color.b = %s(color.b);", dstTFFuncName.c_str());
  158. }
  159. if (colorXformHelper->applyPremul()) {
  160. body.append("color.rgb *= color.a;");
  161. }
  162. body.append("return color;");
  163. SkString colorXformFuncName;
  164. this->emitFunction(kHalf4_GrSLType, "color_xform", SK_ARRAY_COUNT(gColorXformArgs),
  165. gColorXformArgs, body.c_str(), &colorXformFuncName);
  166. out->appendf("%s(%s)", colorXformFuncName.c_str(), srcColor);
  167. }
  168. }
  169. void GrGLSLShaderBuilder::appendColorGamutXform(const char* srcColor,
  170. GrGLSLColorSpaceXformHelper* colorXformHelper) {
  171. SkString xform;
  172. this->appendColorGamutXform(&xform, srcColor, colorXformHelper);
  173. this->codeAppend(xform.c_str());
  174. }
  175. bool GrGLSLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) {
  176. if (featureBit & fFeaturesAddedMask) {
  177. return false;
  178. }
  179. this->extensions().appendf("#extension %s: require\n", extensionName);
  180. fFeaturesAddedMask |= featureBit;
  181. return true;
  182. }
  183. void GrGLSLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
  184. for (int i = 0; i < vars.count(); ++i) {
  185. vars[i].appendDecl(fProgramBuilder->shaderCaps(), out);
  186. out->append(";\n");
  187. }
  188. }
  189. void GrGLSLShaderBuilder::addLayoutQualifier(const char* param, InterfaceQualifier interface) {
  190. SkASSERT(fProgramBuilder->shaderCaps()->generation() >= k330_GrGLSLGeneration ||
  191. fProgramBuilder->shaderCaps()->mustEnableAdvBlendEqs());
  192. fLayoutParams[interface].push_back() = param;
  193. }
  194. void GrGLSLShaderBuilder::compileAndAppendLayoutQualifiers() {
  195. static const char* interfaceQualifierNames[] = {
  196. "in",
  197. "out"
  198. };
  199. for (int interface = 0; interface <= kLastInterfaceQualifier; ++interface) {
  200. const SkTArray<SkString>& params = fLayoutParams[interface];
  201. if (params.empty()) {
  202. continue;
  203. }
  204. this->layoutQualifiers().appendf("layout(%s", params[0].c_str());
  205. for (int i = 1; i < params.count(); ++i) {
  206. this->layoutQualifiers().appendf(", %s", params[i].c_str());
  207. }
  208. this->layoutQualifiers().appendf(") %s;\n", interfaceQualifierNames[interface]);
  209. }
  210. GR_STATIC_ASSERT(0 == GrGLSLShaderBuilder::kIn_InterfaceQualifier);
  211. GR_STATIC_ASSERT(1 == GrGLSLShaderBuilder::kOut_InterfaceQualifier);
  212. GR_STATIC_ASSERT(SK_ARRAY_COUNT(interfaceQualifierNames) == kLastInterfaceQualifier + 1);
  213. }
  214. void GrGLSLShaderBuilder::finalize(uint32_t visibility) {
  215. SkASSERT(!fFinalized);
  216. this->compileAndAppendLayoutQualifiers();
  217. SkASSERT(visibility);
  218. fProgramBuilder->appendUniformDecls((GrShaderFlags) visibility, &this->uniforms());
  219. this->appendDecls(fInputs, &this->inputs());
  220. this->appendDecls(fOutputs, &this->outputs());
  221. this->onFinalize();
  222. // append the 'footer' to code
  223. this->code().append("}");
  224. for (int i = 0; i <= fCodeIndex; i++) {
  225. fCompilerString.append(fShaderStrings[i].c_str(), fShaderStrings[i].size());
  226. }
  227. fFinalized = true;
  228. }