blob: b79936ac7a91a8ca033441ea907e9c9482a433bc [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/private/GrContext_Base.h"
Brian Osmanc18a6452021-03-22 11:44:03 -040012#include "src/core/SkVM.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrBaseContextPriv.h"
Brian Salomonf7f54332020-07-28 09:23:35 -040014#include "src/gpu/GrColorInfo.h"
Greg Daniel456f9b52020-03-05 19:14:18 +000015#include "src/gpu/GrTexture.h"
Brian Osman236ddb32021-02-05 12:15:29 -050016#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/sksl/SkSLUtil.h"
Brian Osman690b6f32021-02-05 16:30:34 -050018#include "src/sksl/ir/SkSLVarDeclarations.h"
Robert Phillips1efecea2019-02-15 16:58:40 -050019
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
21#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
22#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
Ethan Nicholas00543112018-07-31 09:44:36 -040023
Ethan Nicholaseace9352018-10-15 20:09:54 +000024class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
25public:
Ethan Nicholaseace9352018-10-15 20:09:54 +000026 void emitCode(EmitArgs& args) override {
Brian Osman690b6f32021-02-05 16:30:34 -050027 const GrSkSLFP& fp = args.fFp.cast<GrSkSLFP>();
28 const SkSL::Program& program = *fp.fEffect->fBaseProgram;
29
Brian Osmanac9d3f62020-06-25 11:07:30 -040030 // We need to ensure that we emit each child's helper function at least once.
Brian Osman87e3bef2020-01-27 16:21:34 -050031 // Any child FP that isn't sampled won't trigger a call otherwise, leading to asserts later.
Ethan Nicholaseace9352018-10-15 20:09:54 +000032 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Osmana7685b22020-07-10 14:08:56 -040033 if (this->childProcessor(i)) {
34 this->emitChildFunction(i, args);
35 }
Ethan Nicholaseace9352018-10-15 20:09:54 +000036 }
Brian Osman690b6f32021-02-05 16:30:34 -050037
38 class FPCallbacks : public SkSL::PipelineStage::Callbacks {
39 public:
40 FPCallbacks(GrGLSLSkSLFP* self, EmitArgs& args, const SkSL::Context& context)
41 : fSelf(self), fArgs(args), fContext(context) {}
42
43 using String = SkSL::String;
44
45 String declareUniform(const SkSL::VarDeclaration* decl) override {
46 const SkSL::Variable& var = decl->var();
47 if (var.type().isOpaque()) {
48 // Nothing to do. The only opaque type we should see is fragmentProcessor, and
49 // those (children) are handled specially, above.
Brian Osman39675882021-03-31 14:37:10 -040050 SkASSERT(var.type().isFragmentProcessor());
Brian Osman690b6f32021-02-05 16:30:34 -050051 return String(var.name());
52 }
53
54 const SkSL::Type* type = &var.type();
55 bool isArray = false;
56 if (type->isArray()) {
57 type = &type->componentType();
58 isArray = true;
59 }
60
61 GrSLType gpuType;
62 SkAssertResult(SkSL::type_to_grsltype(fContext, *type, &gpuType));
63 const char* uniformName = nullptr;
64 auto handle =
65 fArgs.fUniformHandler->addUniformArray(&fArgs.fFp.cast<GrSkSLFP>(),
66 kFragment_GrShaderFlag,
67 gpuType,
68 SkString(var.name()).c_str(),
69 isArray ? var.type().columns() : 0,
70 &uniformName);
71 fSelf->fUniformHandles.push_back(handle);
72 return String(uniformName);
73 }
74
Brian Osman55761ae2021-02-09 16:52:53 -050075 String getMangledName(const char* name) override {
76 return String(fArgs.fFragBuilder->getMangledFunctionName(name).c_str());
77 }
78
79 void defineFunction(const char* decl, const char* body, bool isMain) override {
80 if (isMain) {
81 fArgs.fFragBuilder->codeAppend(body);
Brian Osman690b6f32021-02-05 16:30:34 -050082 } else {
Brian Osman55761ae2021-02-09 16:52:53 -050083 fArgs.fFragBuilder->emitFunction(decl, body);
Brian Osman690b6f32021-02-05 16:30:34 -050084 }
85 }
86
Brian Osman8e756f32021-02-10 10:19:27 -050087 void defineStruct(const char* definition) override {
88 fArgs.fFragBuilder->definitionAppend(definition);
89 }
90
Brian Osman5e603c32021-02-17 15:39:06 -050091 void declareGlobal(const char* declaration) override {
92 fArgs.fFragBuilder->definitionAppend(declaration);
93 }
94
Brian Osman690b6f32021-02-05 16:30:34 -050095 String sampleChild(int index, String coords) override {
96 return String(fSelf->invokeChild(index, fArgs, coords).c_str());
97 }
98
99 String sampleChildWithMatrix(int index, String matrix) override {
100 // If the child is sampled with a uniform matrix, we need to pass the empty string.
101 // 'invokeChildWithMatrix' will assert that the passed-in matrix matches the one
102 // extracted from the SkSL when the sample usages were determined. We've mangled
103 // the uniform names, though, so it won't match.
104 const GrFragmentProcessor* child = fArgs.fFp.childProcessor(index);
105 const bool hasUniformMatrix = child && child->sampleUsage().hasUniformMatrix();
106 return String(
107 fSelf->invokeChildWithMatrix(index, fArgs, hasUniformMatrix ? "" : matrix)
108 .c_str());
109 }
110
111 GrGLSLSkSLFP* fSelf;
112 EmitArgs& fArgs;
113 const SkSL::Context& fContext;
114 };
115
116 FPCallbacks callbacks(this, args, *program.fContext);
117
118 // Callback to define a function (and return its mangled name)
119 SkString coordsVarName = args.fFragBuilder->newTmpVarName("coords");
Brian Osmanb4ce9442020-11-11 09:18:02 -0500120 const char* coords = nullptr;
121 if (fp.referencesSampleCoords()) {
122 coords = coordsVarName.c_str();
Brian Osman690b6f32021-02-05 16:30:34 -0500123 args.fFragBuilder->codeAppendf("float2 %s = %s;\n", coords, args.fSampleCoord);
Brian Osmanb4ce9442020-11-11 09:18:02 -0500124 }
Brian Osman690b6f32021-02-05 16:30:34 -0500125
126 SkSL::PipelineStage::ConvertProgram(program, coords, &callbacks);
Ethan Nicholasce008112018-08-30 09:19:50 -0400127 }
128
Ethan Nicholaseace9352018-10-15 20:09:54 +0000129 void onSetData(const GrGLSLProgramDataManager& pdman,
130 const GrFragmentProcessor& _proc) override {
Brian Osmand18967c2021-04-01 09:56:07 -0400131 using Type = SkRuntimeEffect::Uniform::Type;
Brian Osmand927bd22019-12-18 11:23:12 -0500132 size_t uniIndex = 0;
Ethan Nicholaseace9352018-10-15 20:09:54 +0000133 const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
Brian Osmana4b91692020-08-10 14:26:16 -0400134 const uint8_t* uniformData = outer.fUniforms->bytes();
135 for (const auto& v : outer.fEffect->uniforms()) {
Brian Osmand18967c2021-04-01 09:56:07 -0400136 const UniformHandle handle = fUniformHandles[uniIndex++];
137 auto floatData = [=] { return SkTAddOffset<const float>(uniformData, v.offset); };
138 auto intData = [=] { return SkTAddOffset<const int>(uniformData, v.offset); };
Brian Osmand76d1862021-02-03 14:48:41 -0500139 switch (v.type) {
Brian Osmand18967c2021-04-01 09:56:07 -0400140 case Type::kFloat: pdman.set1fv(handle, v.count, floatData()); break;
141 case Type::kFloat2: pdman.set2fv(handle, v.count, floatData()); break;
142 case Type::kFloat3: pdman.set3fv(handle, v.count, floatData()); break;
143 case Type::kFloat4: pdman.set4fv(handle, v.count, floatData()); break;
144
145 case Type::kFloat2x2: pdman.setMatrix2fv(handle, v.count, floatData()); break;
146 case Type::kFloat3x3: pdman.setMatrix3fv(handle, v.count, floatData()); break;
147 case Type::kFloat4x4: pdman.setMatrix4fv(handle, v.count, floatData()); break;
148
149 case Type::kInt: pdman.set1iv(handle, v.count, intData()); break;
150 case Type::kInt2: pdman.set2iv(handle, v.count, intData()); break;
151 case Type::kInt3: pdman.set3iv(handle, v.count, intData()); break;
152 case Type::kInt4: pdman.set4iv(handle, v.count, intData()); break;
153
Ethan Nicholasc1c686b2019-04-02 17:30:23 -0400154 default:
Brian Osmand927bd22019-12-18 11:23:12 -0500155 SkDEBUGFAIL("Unsupported uniform type");
156 break;
Ethan Nicholas222e2752018-10-11 11:21:34 -0400157 }
Ethan Nicholas222e2752018-10-11 11:21:34 -0400158 }
159 }
Ethan Nicholaseace9352018-10-15 20:09:54 +0000160
Ethan Nicholaseace9352018-10-15 20:09:54 +0000161 std::vector<UniformHandle> fUniformHandles;
162};
163
Brian Osman7b1678a2019-12-16 09:17:25 -0500164std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, sk_sp<SkRuntimeEffect> effect,
Brian Osmana4b91692020-08-10 14:26:16 -0400165 const char* name, sk_sp<SkData> uniforms) {
166 if (uniforms->size() != effect->uniformSize()) {
Brian Osman9bfd5952020-02-05 10:51:44 -0500167 return nullptr;
168 }
Brian Osmand7e76592020-11-02 12:26:22 -0500169 return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().getShaderErrorHandler(),
170 std::move(effect), name, std::move(uniforms)));
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500171}
172
Brian Osmanc18a6452021-03-22 11:44:03 -0400173GrSkSLFP::GrSkSLFP(ShaderErrorHandler* shaderErrorHandler,
174 sk_sp<SkRuntimeEffect> effect,
175 const char* name,
176 sk_sp<SkData> uniforms)
177 : INHERITED(kGrSkSLFP_ClassID,
178 effect->fAllowColorFilter ? kConstantOutputForConstantInput_OptimizationFlag
179 : kNone_OptimizationFlags)
Brian Osmanbd4f8722020-03-06 15:23:54 -0500180 , fShaderErrorHandler(shaderErrorHandler)
Brian Osman7b1678a2019-12-16 09:17:25 -0500181 , fEffect(std::move(effect))
Ethan Nicholas00543112018-07-31 09:44:36 -0400182 , fName(name)
Brian Osmana4b91692020-08-10 14:26:16 -0400183 , fUniforms(std::move(uniforms)) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400184 if (fEffect->usesSampleCoords()) {
185 this->setUsesSampleCoordsDirectly();
186 }
Ethan Nicholaseace9352018-10-15 20:09:54 +0000187}
Ethan Nicholas00543112018-07-31 09:44:36 -0400188
189GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
Brian Osmanc18a6452021-03-22 11:44:03 -0400190 : INHERITED(kGrSkSLFP_ClassID, other.optimizationFlags())
Brian Osmanbd4f8722020-03-06 15:23:54 -0500191 , fShaderErrorHandler(other.fShaderErrorHandler)
Brian Osman7b1678a2019-12-16 09:17:25 -0500192 , fEffect(other.fEffect)
Ethan Nicholas00543112018-07-31 09:44:36 -0400193 , fName(other.fName)
Brian Osmana4b91692020-08-10 14:26:16 -0400194 , fUniforms(other.fUniforms) {
Michael Ludwige88320b2020-06-24 09:04:56 -0400195 if (fEffect->usesSampleCoords()) {
196 this->setUsesSampleCoordsDirectly();
197 }
Brian Osmana7685b22020-07-10 14:08:56 -0400198
199 this->cloneAndRegisterAllChildProcessors(other);
Ethan Nicholaseace9352018-10-15 20:09:54 +0000200}
Ethan Nicholas00543112018-07-31 09:44:36 -0400201
202const char* GrSkSLFP::name() const {
203 return fName;
204}
205
Ethan Nicholasce008112018-08-30 09:19:50 -0400206void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
Brian Osmanbe1b8372020-06-18 13:40:26 -0400207 int childIndex = this->numChildProcessors();
Brian Osman1298bc42020-06-30 13:39:35 -0400208 SkASSERT((size_t)childIndex < fEffect->fSampleUsages.size());
Brian Osmanc18a6452021-03-22 11:44:03 -0400209 this->mergeOptimizationFlags(ProcessorOptimizationFlags(child.get()));
Brian Osman1298bc42020-06-30 13:39:35 -0400210 this->registerChild(std::move(child), fEffect->fSampleUsages[childIndex]);
Ethan Nicholasce008112018-08-30 09:19:50 -0400211}
212
Brian Salomon18ab2032021-02-23 10:07:05 -0500213std::unique_ptr<GrGLSLFragmentProcessor> GrSkSLFP::onMakeProgramImpl() const {
214 return std::make_unique<GrGLSLSkSLFP>();
Greg Danielf4107942019-12-12 01:02:48 +0000215}
216
Brian Osmand927bd22019-12-18 11:23:12 -0500217void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
Brian Osmana4b91692020-08-10 14:26:16 -0400218 // In the unlikely event of a hash collision, we also include the uniform size in the key.
Brian Osman32253062020-02-05 11:37:08 -0500219 // That ensures that we will (at worst) use the wrong program, but one that expects the same
Brian Osmana4b91692020-08-10 14:26:16 -0400220 // amount of uniform data.
Brian Osman32253062020-02-05 11:37:08 -0500221 b->add32(fEffect->hash());
Brian Osmana4b91692020-08-10 14:26:16 -0400222 b->add32(SkToU32(fUniforms->size()));
Ethan Nicholas00543112018-07-31 09:44:36 -0400223}
224
225bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const {
226 const GrSkSLFP& sk = other.cast<GrSkSLFP>();
Brian Osmana4b91692020-08-10 14:26:16 -0400227 return fEffect->hash() == sk.fEffect->hash() && fUniforms->equals(sk.fUniforms.get());
Ethan Nicholas00543112018-07-31 09:44:36 -0400228}
229
230std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
Brian Osmana7685b22020-07-10 14:08:56 -0400231 return std::unique_ptr<GrFragmentProcessor>(new GrSkSLFP(*this));
Ethan Nicholas00543112018-07-31 09:44:36 -0400232}
233
Brian Osmanc18a6452021-03-22 11:44:03 -0400234SkPMColor4f GrSkSLFP::constantOutputForConstantInput(const SkPMColor4f& inputColor) const {
235 const skvm::Program* program = fEffect->getFilterColorProgram();
236 SkASSERT(program);
237
238 SkSTArray<2, SkPMColor4f, true> childColors;
239 for (int i = 0; i < this->numChildProcessors(); ++i) {
240 childColors.push_back(ConstantOutputForConstantInput(this->childProcessor(i), inputColor));
241 }
242
243 SkPMColor4f result;
244 program->eval(1, childColors.begin(), fUniforms->data(), result.vec());
245 return result;
246}
247
Robert Phillips7f11fb52019-12-03 13:35:19 -0500248/**************************************************************************************************/
Ethan Nicholas00543112018-07-31 09:44:36 -0400249
250GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP);
251
252#if GR_TEST_UTILS
253
Mike Kleina73819b2020-04-17 08:26:30 -0500254#include "include/effects/SkOverdrawColorFilter.h"
Mike Reedb11e6272020-06-24 16:56:33 -0400255#include "src/core/SkColorFilterBase.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500256#include "src/gpu/effects/generated/GrConstColorProcessor.h"
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400257
Ethan Nicholas78aceb22018-08-31 16:13:58 -0400258extern const char* SKSL_OVERDRAW_SRC;
Ethan Nicholas00543112018-07-31 09:44:36 -0400259
Ethan Nicholas00543112018-07-31 09:44:36 -0400260std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
John Stilesa9c9b532020-07-09 17:13:13 -0400261 SkColor colors[SkOverdrawColorFilter::kNumColors];
262 for (SkColor& c : colors) {
263 c = d->fRandom->nextU();
Ethan Nicholas00543112018-07-31 09:44:36 -0400264 }
John Stilesa9c9b532020-07-09 17:13:13 -0400265 auto filter = SkOverdrawColorFilter::MakeWithSkColors(colors);
266 auto [success, fp] = as_CFB(filter)->asFragmentProcessor(/*inputFP=*/nullptr, d->context(),
267 GrColorInfo{});
268 SkASSERT(success);
269 return std::move(fp);
Ethan Nicholas00543112018-07-31 09:44:36 -0400270}
271
272#endif
Brian Salomon5ca24f92021-03-23 17:04:41 -0400273
274/**************************************************************************************************/
275
276GrRuntimeFPBuilder::GrRuntimeFPBuilder(sk_sp<SkRuntimeEffect> effect)
277 : INHERITED(std::move(effect)) {}
278
279GrRuntimeFPBuilder::~GrRuntimeFPBuilder() = default;
280
281std::unique_ptr<GrFragmentProcessor> GrRuntimeFPBuilder::makeFP(
282 GrRecordingContext* recordingContext) {
283 return this->effect()->makeFP(recordingContext,
284 this->uniforms(),
285 this->children(),
286 this->numChildren());
287}