• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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