blob: 2bafaa27150ca0b30f4f2c18f5dbd84265656e3f [file] [log] [blame]
Ethan Nicholas00543112018-07-31 09:44:36 -04001/*
2 * Copyright 2018 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/effects/GrSkSLFP.h"
Robert Phillips1efecea2019-02-15 16:58:40 -05009
Brian Osmanee426f22020-01-02 11:55:24 -050010#include "include/effects/SkRuntimeEffect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/gpu/GrTexture.h"
12#include "include/private/GrContext_Base.h"
13#include "src/gpu/GrBaseContextPriv.h"
14#include "src/sksl/SkSLUtil.h"
Robert Phillips1efecea2019-02-15 16:58:40 -050015
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
17#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
18#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
Ethan Nicholas00543112018-07-31 09:44:36 -040019
Ethan Nicholaseace9352018-10-15 20:09:54 +000020class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
21public:
Brian Osman300fe1d2020-01-23 15:42:43 -050022 GrGLSLSkSLFP(SkSL::PipelineStageArgs&& args) : fArgs(std::move(args)) {}
Ethan Nicholas00543112018-07-31 09:44:36 -040023
Ethan Nicholasfc671ad2019-11-21 11:14:11 -050024 SkSL::String expandFormatArgs(const SkSL::String& raw,
Brian Salomond4bf54e2020-01-27 17:50:36 +000025 const EmitArgs& args,
26 const std::vector<SkSL::Compiler::FormatArg> formatArgs,
27 const char* coordsName,
28 const std::vector<SkString>& childNames) {
Ethan Nicholasfc671ad2019-11-21 11:14:11 -050029 SkSL::String result;
30 int substringStartIndex = 0;
Brian Salomond4bf54e2020-01-27 17:50:36 +000031 int formatArgIndex = 0;
Ethan Nicholasfc671ad2019-11-21 11:14:11 -050032 for (size_t i = 0; i < raw.length(); ++i) {
33 char c = raw[i];
34 if (c == '%') {
35 result += SkSL::StringFragment(raw.c_str() + substringStartIndex,
36 i - substringStartIndex);
37 ++i;
38 c = raw[i];
39 switch (c) {
40 case 's': {
Brian Salomond4bf54e2020-01-27 17:50:36 +000041 const SkSL::Compiler::FormatArg& arg = formatArgs[formatArgIndex++];
Ethan Nicholasfc671ad2019-11-21 11:14:11 -050042 switch (arg.fKind) {
43 case SkSL::Compiler::FormatArg::Kind::kInput:
44 result += args.fInputColor;
45 break;
46 case SkSL::Compiler::FormatArg::Kind::kOutput:
47 result += args.fOutputColor;
48 break;
49 case SkSL::Compiler::FormatArg::Kind::kCoordX:
50 result += coordsName;
51 result += ".x";
52 break;
53 case SkSL::Compiler::FormatArg::Kind::kCoordY:
54 result += coordsName;
55 result += ".y";
56 break;
57 case SkSL::Compiler::FormatArg::Kind::kUniform:
58 result += args.fUniformHandler->getUniformCStr(
59 fUniformHandles[arg.fIndex]);
60 break;
Brian Salomond4bf54e2020-01-27 17:50:36 +000061 case SkSL::Compiler::FormatArg::Kind::kChildProcessor:
62 result += childNames[arg.fIndex].c_str();
Ethan Nicholasfc671ad2019-11-21 11:14:11 -050063 break;
64 case SkSL::Compiler::FormatArg::Kind::kFunctionName:
65 SkASSERT((int) fFunctionNames.size() > arg.fIndex);
66 result += fFunctionNames[arg.fIndex].c_str();
67 break;
68 }
69 break;
70 }
71 default:
72 result += c;
73 }
74 substringStartIndex = i + 1;
75 }
76 }
77 result += SkSL::StringFragment(raw.c_str() + substringStartIndex,
78 raw.length() - substringStartIndex);
79 return result;
80 }
81
Ethan Nicholaseace9352018-10-15 20:09:54 +000082 void emitCode(EmitArgs& args) override {
Brian Osman7b1678a2019-12-16 09:17:25 -050083 const GrSkSLFP& fp = args.fFp.cast<GrSkSLFP>();
Brian Osmanf72dedd2020-01-08 13:19:58 -050084 for (const auto& v : fp.fEffect->inputs()) {
Brian Osmand927bd22019-12-18 11:23:12 -050085 if (v.fQualifier == SkRuntimeEffect::Variable::Qualifier::kUniform) {
86 auto handle = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
87 v.fGPUType,
88 v.fName.c_str(),
89 v.isArray() ? v.fCount : 0);
90 fUniformHandles.push_back(handle);
Ethan Nicholaseace9352018-10-15 20:09:54 +000091 }
Ethan Nicholasce008112018-08-30 09:19:50 -040092 }
Brian Osman2e29ab52019-09-20 12:19:11 -040093 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Brian Osmanfd7fd962020-01-28 00:27:41 +000094 SkString coords = args.fTransformedCoords.count()
95 ? fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint)
96 : SkString("sk_FragCoord");
Brian Salomond4bf54e2020-01-27 17:50:36 +000097 std::vector<SkString> childNames;
Ethan Nicholaseace9352018-10-15 20:09:54 +000098 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Salomond4bf54e2020-01-27 17:50:36 +000099 childNames.push_back(this->invokeChild(i, args));
Ethan Nicholaseace9352018-10-15 20:09:54 +0000100 }
Brian Osman300fe1d2020-01-23 15:42:43 -0500101 for (const auto& f : fArgs.fFunctions) {
Ethan Nicholasfc671ad2019-11-21 11:14:11 -0500102 fFunctionNames.emplace_back();
Brian Salomond4bf54e2020-01-27 17:50:36 +0000103 SkSL::String body = this->expandFormatArgs(f.fBody.c_str(), args, f.fFormatArgs,
104 coords.c_str(), childNames);
Ethan Nicholasfc671ad2019-11-21 11:14:11 -0500105 fragBuilder->emitFunction(f.fReturnType,
106 f.fName.c_str(),
107 f.fParameters.size(),
108 f.fParameters.data(),
109 body.c_str(),
110 &fFunctionNames.back());
Ethan Nicholasce008112018-08-30 09:19:50 -0400111 }
Brian Salomond4bf54e2020-01-27 17:50:36 +0000112 fragBuilder->codeAppend(this->expandFormatArgs(fArgs.fCode.c_str(), args, fArgs.fFormatArgs,
113 coords.c_str(), childNames).c_str());
Ethan Nicholasce008112018-08-30 09:19:50 -0400114 }
115
Ethan Nicholaseace9352018-10-15 20:09:54 +0000116 void onSetData(const GrGLSLProgramDataManager& pdman,
117 const GrFragmentProcessor& _proc) override {
Brian Osmand927bd22019-12-18 11:23:12 -0500118 size_t uniIndex = 0;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000119 const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
120 char* inputs = (char*) outer.fInputs.get();
Brian Osmanf72dedd2020-01-08 13:19:58 -0500121 for (const auto& v : outer.fEffect->inputs()) {
Brian Osmand927bd22019-12-18 11:23:12 -0500122 if (v.fQualifier != SkRuntimeEffect::Variable::Qualifier::kUniform) {
123 continue;
124 }
125
126 const float* data = reinterpret_cast<const float*>(inputs + v.fOffset);
127 switch (v.fType) {
128 case SkRuntimeEffect::Variable::Type::kFloat:
129 pdman.set1fv(fUniformHandles[uniIndex++], v.fCount, data);
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400130 break;
Brian Osmand927bd22019-12-18 11:23:12 -0500131 case SkRuntimeEffect::Variable::Type::kFloat2:
132 pdman.set2fv(fUniformHandles[uniIndex++], v.fCount, data);
Ethan Nicholasfc671ad2019-11-21 11:14:11 -0500133 break;
Brian Osmand927bd22019-12-18 11:23:12 -0500134 case SkRuntimeEffect::Variable::Type::kFloat3:
135 pdman.set3fv(fUniformHandles[uniIndex++], v.fCount, data);
Ethan Nicholasfc671ad2019-11-21 11:14:11 -0500136 break;
Brian Osmand927bd22019-12-18 11:23:12 -0500137 case SkRuntimeEffect::Variable::Type::kFloat4:
138 pdman.set4fv(fUniformHandles[uniIndex++], v.fCount, data);
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400139 break;
Brian Osmand927bd22019-12-18 11:23:12 -0500140 case SkRuntimeEffect::Variable::Type::kFloat2x2:
141 pdman.setMatrix2fv(fUniformHandles[uniIndex++], v.fCount, data);
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400142 break;
Brian Osmand927bd22019-12-18 11:23:12 -0500143 case SkRuntimeEffect::Variable::Type::kFloat3x3:
144 pdman.setMatrix3fv(fUniformHandles[uniIndex++], v.fCount, data);
145 break;
146 case SkRuntimeEffect::Variable::Type::kFloat4x4:
147 pdman.setMatrix4fv(fUniformHandles[uniIndex++], v.fCount, data);
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400148 break;
149 default:
Brian Osmand927bd22019-12-18 11:23:12 -0500150 SkDEBUGFAIL("Unsupported uniform type");
151 break;
Ethan Nicholas222e2752018-10-11 11:21:34 -0400152 }
Ethan Nicholas222e2752018-10-11 11:21:34 -0400153 }
154 }
Ethan Nicholaseace9352018-10-15 20:09:54 +0000155
Ethan Nicholaseace9352018-10-15 20:09:54 +0000156 // nearly-finished GLSL; still contains printf-style "%s" format tokens
Brian Osman300fe1d2020-01-23 15:42:43 -0500157 SkSL::PipelineStageArgs fArgs;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000158 std::vector<UniformHandle> fUniformHandles;
Brian Osman2e29ab52019-09-20 12:19:11 -0400159 std::vector<SkString> fFunctionNames;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000160};
161
Brian Osman7b1678a2019-12-16 09:17:25 -0500162std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, sk_sp<SkRuntimeEffect> effect,
163 const char* name, const void* inputs, size_t inputSize,
Brian Osman3b1e4c22019-08-12 15:12:14 -0400164 const SkMatrix* matrix) {
Brian Osman7b1678a2019-12-16 09:17:25 -0500165 return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().caps()->refShaderCaps(),
166 std::move(effect), name, inputs, inputSize,
167 matrix));
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500168}
169
Brian Osman7b1678a2019-12-16 09:17:25 -0500170GrSkSLFP::GrSkSLFP(sk_sp<const GrShaderCaps> shaderCaps, sk_sp<SkRuntimeEffect> effect,
171 const char* name, const void* inputs, size_t inputSize, const SkMatrix* matrix)
Ethan Nicholas00543112018-07-31 09:44:36 -0400172 : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
Brian Osman7b1678a2019-12-16 09:17:25 -0500173 , fShaderCaps(std::move(shaderCaps))
174 , fEffect(std::move(effect))
Ethan Nicholas00543112018-07-31 09:44:36 -0400175 , fName(name)
Ethan Nicholaseace9352018-10-15 20:09:54 +0000176 , fInputs(new int8_t[inputSize])
177 , fInputSize(inputSize) {
Ethan Nicholas0d997662019-04-08 09:46:01 -0400178 if (fInputSize) {
179 memcpy(fInputs.get(), inputs, inputSize);
180 }
Brian Osman3b1e4c22019-08-12 15:12:14 -0400181 if (matrix) {
182 fCoordTransform = GrCoordTransform(*matrix);
Brian Osmanfd7fd962020-01-28 00:27:41 +0000183 this->addCoordTransform(&fCoordTransform);
Brian Osman3b1e4c22019-08-12 15:12:14 -0400184 }
Ethan Nicholaseace9352018-10-15 20:09:54 +0000185}
Ethan Nicholas00543112018-07-31 09:44:36 -0400186
187GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
188 : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
Brian Osman7b1678a2019-12-16 09:17:25 -0500189 , fShaderCaps(other.fShaderCaps)
190 , fEffect(other.fEffect)
Ethan Nicholas00543112018-07-31 09:44:36 -0400191 , fName(other.fName)
Ethan Nicholaseace9352018-10-15 20:09:54 +0000192 , fInputs(new int8_t[other.fInputSize])
193 , fInputSize(other.fInputSize) {
Ethan Nicholas0d997662019-04-08 09:46:01 -0400194 if (fInputSize) {
195 memcpy(fInputs.get(), other.fInputs.get(), fInputSize);
196 }
Brian Osmanfd7fd962020-01-28 00:27:41 +0000197 if (other.numCoordTransforms()) {
198 fCoordTransform = other.fCoordTransform;
199 this->addCoordTransform(&fCoordTransform);
200 }
Ethan Nicholaseace9352018-10-15 20:09:54 +0000201}
Ethan Nicholas00543112018-07-31 09:44:36 -0400202
203const char* GrSkSLFP::name() const {
204 return fName;
205}
206
Ethan Nicholasce008112018-08-30 09:19:50 -0400207void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
208 this->registerChildProcessor(std::move(child));
209}
210
Ethan Nicholas00543112018-07-31 09:44:36 -0400211GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
Brian Osman7b1678a2019-12-16 09:17:25 -0500212 // Note: This is actually SkSL (again) but with inline format specifiers.
Brian Osman107c6662019-12-30 15:02:30 -0500213 SkSL::PipelineStageArgs args;
214 SkAssertResult(fEffect->toPipelineStage(fInputs.get(), fShaderCaps.get(), &args));
Brian Osman300fe1d2020-01-23 15:42:43 -0500215 return new GrGLSLSkSLFP(std::move(args));
Greg Danielf4107942019-12-12 01:02:48 +0000216}
217
Brian Osmand927bd22019-12-18 11:23:12 -0500218void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
Brian Osman7b1678a2019-12-16 09:17:25 -0500219 b->add32(fEffect->index());
Ethan Nicholaseace9352018-10-15 20:09:54 +0000220 char* inputs = (char*) fInputs.get();
Brian Osmanf72dedd2020-01-08 13:19:58 -0500221 for (const auto& v : fEffect->inputs()) {
Brian Osmand927bd22019-12-18 11:23:12 -0500222 if (v.fQualifier != SkRuntimeEffect::Variable::Qualifier::kIn) {
Ethan Nicholasce008112018-08-30 09:19:50 -0400223 continue;
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400224 }
Brian Osmand927bd22019-12-18 11:23:12 -0500225 // 'in' arrays are not supported
226 SkASSERT(!v.isArray());
227 switch (v.fType) {
228 case SkRuntimeEffect::Variable::Type::kBool:
229 b->add32(inputs[v.fOffset]);
230 break;
231 case SkRuntimeEffect::Variable::Type::kInt:
232 case SkRuntimeEffect::Variable::Type::kFloat:
233 b->add32(*(int32_t*)(inputs + v.fOffset));
234 break;
235 default:
236 SkDEBUGFAIL("Unsupported input variable type");
237 break;
Ethan Nicholas00543112018-07-31 09:44:36 -0400238 }
239 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400240}
241
242bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const {
243 const GrSkSLFP& sk = other.cast<GrSkSLFP>();
Brian Osman7b1678a2019-12-16 09:17:25 -0500244 SkASSERT(fEffect->index() != sk.fEffect->index() || fInputSize == sk.fInputSize);
245 return fEffect->index() == sk.fEffect->index() &&
Ethan Nicholaseace9352018-10-15 20:09:54 +0000246 !memcmp(fInputs.get(), sk.fInputs.get(), fInputSize);
Ethan Nicholas00543112018-07-31 09:44:36 -0400247}
248
249std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
Ethan Nicholaseace9352018-10-15 20:09:54 +0000250 std::unique_ptr<GrSkSLFP> result(new GrSkSLFP(*this));
Ethan Nicholasce008112018-08-30 09:19:50 -0400251 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Salomond4bf54e2020-01-27 17:50:36 +0000252 result->registerChildProcessor(this->childProcessor(i).clone());
Ethan Nicholasce008112018-08-30 09:19:50 -0400253 }
254 return std::unique_ptr<GrFragmentProcessor>(result.release());
Ethan Nicholas00543112018-07-31 09:44:36 -0400255}
256
Robert Phillips7f11fb52019-12-03 13:35:19 -0500257/**************************************************************************************************/
Ethan Nicholas00543112018-07-31 09:44:36 -0400258
259GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP);
260
261#if GR_TEST_UTILS
262
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500263#include "include/effects/SkArithmeticImageFilter.h"
264#include "include/gpu/GrContext.h"
265#include "src/gpu/effects/generated/GrConstColorProcessor.h"
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400266
267extern const char* SKSL_ARITHMETIC_SRC;
268extern const char* SKSL_DITHER_SRC;
269extern const char* SKSL_OVERDRAW_SRC;
Ethan Nicholas00543112018-07-31 09:44:36 -0400270
271using Value = SkSL::Program::Settings::Value;
272
273std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
Ethan Nicholaseace9352018-10-15 20:09:54 +0000274 int type = d->fRandom->nextULessThan(3);
Ethan Nicholas00543112018-07-31 09:44:36 -0400275 switch (type) {
276 case 0: {
Brian Osman088913a2019-12-19 15:44:56 -0500277 static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_DITHER_SRC)));
Ethan Nicholas00543112018-07-31 09:44:36 -0400278 int rangeType = d->fRandom->nextULessThan(3);
Brian Osman088913a2019-12-19 15:44:56 -0500279 auto result = GrSkSLFP::Make(d->context(), effect, "Dither",
Brian Osman7b1678a2019-12-16 09:17:25 -0500280 &rangeType, sizeof(rangeType));
Ethan Nicholasce008112018-08-30 09:19:50 -0400281 return std::unique_ptr<GrFragmentProcessor>(result.release());
282 }
283 case 1: {
Brian Osman088913a2019-12-19 15:44:56 -0500284 static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_ARITHMETIC_SRC)));
Ethan Nicholasce008112018-08-30 09:19:50 -0400285 ArithmeticFPInputs inputs;
286 inputs.k[0] = d->fRandom->nextF();
287 inputs.k[1] = d->fRandom->nextF();
288 inputs.k[2] = d->fRandom->nextF();
289 inputs.k[3] = d->fRandom->nextF();
290 inputs.enforcePMColor = d->fRandom->nextBool();
Brian Osman088913a2019-12-19 15:44:56 -0500291 auto result = GrSkSLFP::Make(d->context(), effect, "Arithmetic",
Brian Osman7b1678a2019-12-16 09:17:25 -0500292 &inputs, sizeof(inputs));
Ethan Nicholasce008112018-08-30 09:19:50 -0400293 result->addChild(GrConstColorProcessor::Make(
Brian Osmanf28e55d2018-10-03 16:35:54 -0400294 SK_PMColor4fWHITE,
Ethan Nicholasce008112018-08-30 09:19:50 -0400295 GrConstColorProcessor::InputMode::kIgnore));
296 return std::unique_ptr<GrFragmentProcessor>(result.release());
Ethan Nicholas00543112018-07-31 09:44:36 -0400297 }
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400298 case 2: {
Brian Osman088913a2019-12-19 15:44:56 -0500299 static auto effect = std::get<0>(SkRuntimeEffect::Make(SkString(SKSL_OVERDRAW_SRC)));
Brian Osman9d10abe2019-12-13 16:31:40 -0500300 SkColor4f inputs[6];
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400301 for (int i = 0; i < 6; ++i) {
Brian Osman9d10abe2019-12-13 16:31:40 -0500302 inputs[i] = SkColor4f::FromBytes_RGBA(d->fRandom->nextU());
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400303 }
Brian Osman088913a2019-12-19 15:44:56 -0500304 auto result = GrSkSLFP::Make(d->context(), effect, "Overdraw",
Brian Osman7b1678a2019-12-16 09:17:25 -0500305 &inputs, sizeof(inputs));
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400306 return std::unique_ptr<GrFragmentProcessor>(result.release());
307 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400308 }
309 SK_ABORT("unreachable");
Ethan Nicholas00543112018-07-31 09:44:36 -0400310}
311
312#endif