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