1 /*
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
8 #include "GrSkSLFP.h"
9 #include "glsl/GrGLSLFragmentProcessor.h"
10 #include "glsl/GrGLSLFragmentShaderBuilder.h"
11 #include "glsl/GrGLSLProgramBuilder.h"
12 #include "GrContext.h"
13 #include "GrContextPriv.h"
14 #include "GrTexture.h"
15 #include "SkSLUtil.h"
16
GrSkSLFPFactory(const char * name,const GrShaderCaps * shaderCaps,const char * sksl)17 GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl)
18 : fName(name) {
19 SkSL::Program::Settings settings;
20 settings.fCaps = shaderCaps;
21 fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind,
22 SkSL::String(sksl),
23 settings);
24 if (fCompiler.errorCount()) {
25 SkDebugf("%s\n", fCompiler.errorText().c_str());
26 }
27 SkASSERT(fBaseProgram);
28 SkASSERT(!fCompiler.errorCount());
29 for (const auto& e : *fBaseProgram) {
30 if (e.fKind == SkSL::ProgramElement::kVar_Kind) {
31 SkSL::VarDeclarations& v = (SkSL::VarDeclarations&) e;
32 for (const auto& varStatement : v.fVars) {
33 const SkSL::Variable& var = *((SkSL::VarDeclaration&) *varStatement).fVar;
34 if (var.fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
35 fInputVars.push_back(&var);
36 }
37 if (var.fModifiers.fLayout.fKey) {
38 fKeyVars.push_back(&var);
39 }
40 }
41 }
42 }
43 }
44
getSpecialization(const SkSL::String & key,const void * inputs,size_t inputSize)45 const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs,
46 size_t inputSize) {
47 const auto& found = fSpecializations.find(key);
48 if (found != fSpecializations.end()) {
49 return found->second.get();
50 }
51
52 std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap;
53 size_t offset = 0;
54 for (const auto& v : fInputVars) {
55 SkSL::String name(v->fName);
56 if (&v->fType == fCompiler.context().fInt_Type.get()) {
57 offset = SkAlign4(offset);
58 int32_t v = *(int32_t*) (((uint8_t*) inputs) + offset);
59 inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
60 offset += sizeof(int32_t);
61 } else if (&v->fType == fCompiler.context().fBool_Type.get()) {
62 bool v = *(((bool*) inputs) + offset);
63 inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
64 offset += sizeof(bool);
65 } else if (&v->fType == fCompiler.context().fFloat4_Type.get() ||
66 &v->fType == fCompiler.context().fHalf4_Type.get()) {
67 offset = SkAlign4(offset) + sizeof(float) * 4;
68 } else if (&v->fType == fCompiler.context().fFragmentProcessor_Type.get()) {
69 // do nothing
70 } else {
71 printf("can't handle input var: %s\n", SkSL::String(v->fType.fName).c_str());
72 SkASSERT(false);
73 }
74 }
75
76 std::unique_ptr<SkSL::Program> specialized = fCompiler.specialize(*fBaseProgram, inputMap);
77 SkAssertResult(fCompiler.optimize(*specialized));
78 const SkSL::Program* result = specialized.get();
79 fSpecializations.insert(std::make_pair(key, std::move(specialized)));
80 return result;
81 }
82
83 class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
84 public:
GrGLSLSkSLFP(const SkSL::Context * context,const std::vector<const SkSL::Variable * > * inputVars,SkSL::String glsl,std::vector<SkSL::Compiler::FormatArg> formatArgs)85 GrGLSLSkSLFP(const SkSL::Context* context, const std::vector<const SkSL::Variable*>* inputVars,
86 SkSL::String glsl, std::vector<SkSL::Compiler::FormatArg> formatArgs)
87 : fContext(*context)
88 , fInputVars(*inputVars)
89 , fGLSL(glsl)
90 , fFormatArgs(formatArgs) {}
91
uniformType(const SkSL::Type & type)92 GrSLType uniformType(const SkSL::Type& type) {
93 if (type == *fContext.fFloat_Type) {
94 return kFloat_GrSLType;
95 } else if (type == *fContext.fHalf_Type) {
96 return kHalf_GrSLType;
97 } else if (type == *fContext.fFloat2_Type) {
98 return kFloat2_GrSLType;
99 } else if (type == *fContext.fHalf2_Type) {
100 return kHalf2_GrSLType;
101 } else if (type == *fContext.fFloat4_Type) {
102 return kFloat4_GrSLType;
103 } else if (type == *fContext.fHalf4_Type) {
104 return kHalf4_GrSLType;
105 } else if (type == *fContext.fFloat4x4_Type) {
106 return kFloat4x4_GrSLType;
107 } else if (type == *fContext.fHalf4x4_Type) {
108 return kHalf4x4_GrSLType;
109 } else if (type == *fContext.fBool_Type) {
110 return kBool_GrSLType;
111 } else if (type == *fContext.fInt_Type) {
112 return kInt_GrSLType;
113 }
114 printf("%s\n", SkSL::String(type.fName).c_str());
115 SK_ABORT("unsupported uniform type");
116 return kFloat_GrSLType;
117 }
118
emitCode(EmitArgs & args)119 void emitCode(EmitArgs& args) override {
120 for (const auto& v : fInputVars) {
121 if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag && v->fType !=
122 *fContext.fFragmentProcessor_Type) {
123 fUniformHandles.push_back(args.fUniformHandler->addUniform(
124 kFragment_GrShaderFlag,
125 this->uniformType(v->fType),
126 kDefault_GrSLPrecision,
127 SkSL::String(v->fName).c_str()));
128 }
129 }
130 std::vector<SkString> childNames;
131 for (int i = 0; i < this->numChildProcessors(); ++i) {
132 childNames.push_back(SkStringPrintf("_child%d", i));
133 this->emitChild(i, &childNames[i], args);
134 }
135 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
136 int substringStartIndex = 0;
137 int formatArgIndex = 0;
138 for (size_t i = 0; i < fGLSL.length(); ++i) {
139 char c = fGLSL[i];
140 if (c == '%') {
141 fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex,
142 i - substringStartIndex);
143 ++i;
144 c = fGLSL[i];
145 switch (c) {
146 case 's': {
147 SkSL::Compiler::FormatArg& arg = fFormatArgs[formatArgIndex++];
148 switch (arg.fKind) {
149 case SkSL::Compiler::FormatArg::Kind::kInput:
150 fragBuilder->codeAppend(args.fInputColor);
151 break;
152 case SkSL::Compiler::FormatArg::Kind::kOutput:
153 fragBuilder->codeAppend(args.fOutputColor);
154 break;
155 case SkSL::Compiler::FormatArg::Kind::kUniform:
156 fragBuilder->codeAppend(args.fUniformHandler->getUniformCStr(
157 fUniformHandles[arg.fIndex]));
158 break;
159 case SkSL::Compiler::FormatArg::Kind::kChildProcessor:
160 fragBuilder->codeAppend(childNames[arg.fIndex].c_str());
161 break;
162 }
163 break;
164 }
165 default:
166 fragBuilder->codeAppendf("%c", c);
167 }
168 substringStartIndex = i + 1;
169 }
170 }
171 fragBuilder->codeAppend(fGLSL.c_str() + substringStartIndex,
172 fGLSL.length() - substringStartIndex);
173 }
174
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & _proc)175 void onSetData(const GrGLSLProgramDataManager& pdman,
176 const GrFragmentProcessor& _proc) override {
177 size_t uniformIndex = 0;
178 size_t offset = 0;
179 const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
180 char* inputs = (char*) outer.fInputs.get();
181 const SkSL::Context& context = outer.fFactory->fCompiler.context();
182 for (const auto& v : outer.fFactory->fInputVars) {
183 if (&v->fType == context.fFloat4_Type.get() ||
184 &v->fType == context.fHalf4_Type.get()) {
185 float f1, f2, f3, f4;
186 switch (v->fModifiers.fLayout.fCType) {
187 case SkSL::Layout::CType::kSkPMColor:
188 f1 = ((uint8_t*) inputs)[offset++] / 255.0;
189 f2 = ((uint8_t*) inputs)[offset++] / 255.0;
190 f3 = ((uint8_t*) inputs)[offset++] / 255.0;
191 f4 = ((uint8_t*) inputs)[offset++] / 255.0;
192 break;
193 case SkSL::Layout::CType::kSkRect: // fall through
194 case SkSL::Layout::CType::kDefault:
195 offset = SkAlign4(offset);
196 f1 = *(float*) (inputs + offset);
197 offset += sizeof(float);
198 f2 = *(float*) (inputs + offset);
199 offset += sizeof(float);
200 f3 = *(float*) (inputs + offset);
201 offset += sizeof(float);
202 f4 = *(float*) (inputs + offset);
203 offset += sizeof(float);
204 break;
205 default:
206 SK_ABORT("unsupported uniform ctype");
207 }
208 if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
209 pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4);
210 }
211 } else if (&v->fType == context.fInt_Type.get()) {
212 int32_t i = *(int*) (inputs + offset);
213 offset += sizeof(int32_t);
214 if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
215 pdman.set1i(fUniformHandles[uniformIndex++], i);
216 }
217 } else if (&v->fType == context.fBool_Type.get()) {
218 SkASSERT(!(v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag));
219 ++offset;
220 } else {
221 SkASSERT(&v->fType == context.fFragmentProcessor_Type.get());
222 }
223 }
224 }
225
226 const SkSL::Context& fContext;
227 const std::vector<const SkSL::Variable*>& fInputVars;
228 // nearly-finished GLSL; still contains printf-style "%s" format tokens
229 const SkSL::String fGLSL;
230 std::vector<SkSL::Compiler::FormatArg> fFormatArgs;
231 std::vector<UniformHandle> fUniformHandles;
232 };
233
Make(GrContext * context,int index,const char * name,const char * sksl,const void * inputs,size_t inputSize)234 std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext* context, int index, const char* name,
235 const char* sksl, const void* inputs,
236 size_t inputSize) {
237 return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->contextPriv().getFPFactoryCache(),
238 context->contextPriv().caps()->shaderCaps(),
239 index, name, sksl, inputs, inputSize));
240 }
241
GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache,const GrShaderCaps * shaderCaps,int index,const char * name,const char * sksl,const void * inputs,size_t inputSize)242 GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
243 int index, const char* name, const char* sksl, const void* inputs,
244 size_t inputSize)
245 : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
246 , fFactoryCache(factoryCache)
247 , fShaderCaps(sk_ref_sp(shaderCaps))
248 , fIndex(index)
249 , fName(name)
250 , fSkSL(sksl)
251 , fInputs(new int8_t[inputSize])
252 , fInputSize(inputSize) {
253 memcpy(fInputs.get(), inputs, inputSize);
254 }
255
GrSkSLFP(const GrSkSLFP & other)256 GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
257 : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
258 , fFactoryCache(other.fFactoryCache)
259 , fShaderCaps(other.fShaderCaps)
260 , fFactory(other.fFactory)
261 , fIndex(other.fIndex)
262 , fName(other.fName)
263 , fSkSL(other.fSkSL)
264 , fInputs(new int8_t[other.fInputSize])
265 , fInputSize(other.fInputSize) {
266 memcpy(fInputs.get(), other.fInputs.get(), fInputSize);
267 }
268
name() const269 const char* GrSkSLFP::name() const {
270 return fName;
271 }
272
createFactory() const273 void GrSkSLFP::createFactory() const {
274 if (!fFactory) {
275 fFactory = fFactoryCache->get(fIndex);
276 if (!fFactory) {
277 fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL));
278 fFactoryCache->set(fIndex, fFactory);
279 }
280 }
281 }
282
addChild(std::unique_ptr<GrFragmentProcessor> child)283 void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
284 this->registerChildProcessor(std::move(child));
285 }
286
onCreateGLSLInstance() const287 GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
288 this->createFactory();
289 const SkSL::Program* specialized = fFactory->getSpecialization(fKey, fInputs.get(), fInputSize);
290 SkSL::String glsl;
291 std::vector<SkSL::Compiler::FormatArg> formatArgs;
292 if (!fFactory->fCompiler.toPipelineStage(*specialized, &glsl, &formatArgs)) {
293 printf("%s\n", fFactory->fCompiler.errorText().c_str());
294 SkASSERT(false);
295 }
296 return new GrGLSLSkSLFP(specialized->fContext.get(), &fFactory->fInputVars, glsl, formatArgs);
297 }
298
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const299 void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
300 GrProcessorKeyBuilder* b) const {
301 this->createFactory();
302 size_t offset = 0;
303 char* inputs = (char*) fInputs.get();
304 const SkSL::Context& context = fFactory->fCompiler.context();
305 for (const auto& v : fFactory->fInputVars) {
306 if (&v->fType == context.fInt_Type.get()) {
307 offset = SkAlign4(offset);
308 if (v->fModifiers.fLayout.fKey) {
309 fKey += inputs[offset + 0];
310 fKey += inputs[offset + 1];
311 fKey += inputs[offset + 2];
312 fKey += inputs[offset + 3];
313 b->add32(*(int32_t*) (inputs + offset));
314 }
315 offset += sizeof(int32_t);
316 } else if (&v->fType == context.fFloat4_Type.get() ||
317 &v->fType == context.fHalf4_Type.get()) {
318 if (v->fModifiers.fLayout.fKey) {
319 for (size_t i = 0; i < sizeof(float) * 4; ++i) {
320 fKey += inputs[offset + i];
321 }
322 b->add32(*(int32_t*) (inputs + offset));
323 offset += sizeof(float);
324 b->add32(*(int32_t*) (inputs + offset));
325 offset += sizeof(float);
326 b->add32(*(int32_t*) (inputs + offset));
327 offset += sizeof(float);
328 b->add32(*(int32_t*) (inputs + offset));
329 offset += sizeof(float);
330 } else {
331 offset += sizeof(float) * 4;
332 }
333 } else if (&v->fType == context.fBool_Type.get()) {
334 if (v->fModifiers.fLayout.fKey) {
335 fKey += inputs[offset];
336 b->add32(inputs[offset]);
337 }
338 ++offset;
339 } else if (&v->fType == context.fFragmentProcessor_Type.get()) {
340 continue;
341 } else {
342 // unsupported input var type
343 printf("%s\n", SkSL::String(v->fType.fName).c_str());
344 SkASSERT(false);
345 }
346 }
347 }
348
onIsEqual(const GrFragmentProcessor & other) const349 bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const {
350 const GrSkSLFP& sk = other.cast<GrSkSLFP>();
351 SkASSERT(fIndex != sk.fIndex || fInputSize == sk.fInputSize);
352 return fIndex == sk.fIndex &&
353 !memcmp(fInputs.get(), sk.fInputs.get(), fInputSize);
354 }
355
clone() const356 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
357 std::unique_ptr<GrSkSLFP> result(new GrSkSLFP(*this));
358 for (int i = 0; i < this->numChildProcessors(); ++i) {
359 result->registerChildProcessor(this->childProcessor(i).clone());
360 }
361 return std::unique_ptr<GrFragmentProcessor>(result.release());
362 }
363
364 // We have to do a bit of manual refcounting in the cache methods below. Ideally, we could just
365 // define fFactories to contain sk_sp<GrSkSLFPFactory> rather than GrSkSLFPFactory*, but that would
366 // require GrContext to include GrSkSLFP, which creates much bigger headaches than a few manual
367 // refcounts.
368
get(int index)369 sk_sp<GrSkSLFPFactory> GrSkSLFPFactoryCache::get(int index) {
370 if (index >= (int) fFactories.size()) {
371 return nullptr;
372 }
373 GrSkSLFPFactory* result = fFactories[index];
374 SkSafeRef(result);
375 return sk_sp<GrSkSLFPFactory>(result);
376 }
377
set(int index,sk_sp<GrSkSLFPFactory> factory)378 void GrSkSLFPFactoryCache::set(int index, sk_sp<GrSkSLFPFactory> factory) {
379 while (index >= (int) fFactories.size()) {
380 fFactories.emplace_back();
381 }
382 factory->ref();
383 SkASSERT(!fFactories[index]);
384 fFactories[index] = factory.get();
385 }
386
~GrSkSLFPFactoryCache()387 GrSkSLFPFactoryCache::~GrSkSLFPFactoryCache() {
388 for (GrSkSLFPFactory* factory : fFactories) {
389 if (factory) {
390 factory->unref();
391 }
392 }
393 }
394
395 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP);
396
397 #if GR_TEST_UTILS
398
399 #include "GrConstColorProcessor.h"
400 #include "SkArithmeticImageFilter.h"
401
402 extern const char* SKSL_ARITHMETIC_SRC;
403 extern const char* SKSL_DITHER_SRC;
404 extern const char* SKSL_OVERDRAW_SRC;
405
406 using Value = SkSL::Program::Settings::Value;
407
TestCreate(GrProcessorTestData * d)408 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
409 int type = d->fRandom->nextULessThan(3);
410 switch (type) {
411 case 0: {
412 static int ditherIndex = NewIndex();
413 int rangeType = d->fRandom->nextULessThan(3);
414 std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), ditherIndex, "Dither",
415 SKSL_DITHER_SRC, &rangeType,
416 sizeof(rangeType));
417 return std::unique_ptr<GrFragmentProcessor>(result.release());
418 }
419 case 1: {
420 static int arithmeticIndex = NewIndex();
421 ArithmeticFPInputs inputs;
422 inputs.k[0] = d->fRandom->nextF();
423 inputs.k[1] = d->fRandom->nextF();
424 inputs.k[2] = d->fRandom->nextF();
425 inputs.k[3] = d->fRandom->nextF();
426 inputs.enforcePMColor = d->fRandom->nextBool();
427 std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), arithmeticIndex,
428 "Arithmetic", SKSL_ARITHMETIC_SRC,
429 &inputs, sizeof(inputs));
430 result->addChild(GrConstColorProcessor::Make(
431 SK_PMColor4fWHITE,
432 GrConstColorProcessor::InputMode::kIgnore));
433 return std::unique_ptr<GrFragmentProcessor>(result.release());
434 }
435 case 2: {
436 static int overdrawIndex = NewIndex();
437 SkPMColor inputs[6];
438 for (int i = 0; i < 6; ++i) {
439 inputs[i] = d->fRandom->nextU();
440 }
441 std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), overdrawIndex,
442 "Overdraw", SKSL_OVERDRAW_SRC,
443 &inputs, sizeof(inputs));
444 return std::unique_ptr<GrFragmentProcessor>(result.release());
445 }
446 }
447 SK_ABORT("unreachable");
448 return nullptr;
449 }
450
451 #endif
452