diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp index 4031d5effd..606c7b90e7 100644 --- a/src/core/SkColorFilter.cpp +++ b/src/core/SkColorFilter.cpp @@ -443,16 +443,13 @@ sk_sp SkColorFilters::Lerp(float weight, sk_sp cf0 return cf1; } - static SkRuntimeEffect* effect = [&]{ - auto [effect,err] = SkRuntimeEffect::Make(SkString{ - "uniform shader cf0;" - "uniform shader cf1;" - "uniform half weight;" - "half4 main() { return mix(sample(cf0), sample(cf1), weight); }" - }); - SkASSERT(effect && err.isEmpty()); - return effect.release(); - }(); + auto [effect,err] = SkRuntimeEffect::Make(SkString{ + "uniform shader cf0;" + "uniform shader cf1;" + "uniform half weight;" + "half4 main() { return mix(sample(cf0), sample(cf1), weight); }" + }); + SkASSERT(effect && err.isEmpty()); sk_sp inputs[] = {cf0,cf1}; return effect->makeColorFilter(SkData::MakeWithCopy(&weight, sizeof(weight)), diff --git a/src/core/SkLRUCache.h b/src/core/SkLRUCache.h index d5be4f3a9b..50429d500f 100644 --- a/src/core/SkLRUCache.h +++ b/src/core/SkLRUCache.h @@ -56,6 +56,8 @@ public: } V* insert(const K& key, V value) { + SkASSERT(!this->find(key)); + Entry* entry = new Entry(key, std::move(value)); fMap.set(entry); fLRU.addToHead(entry); @@ -65,6 +67,15 @@ public: return &entry->fValue; } + V* insert_or_update(const K& key, V value) { + if (V* found = this->find(key)) { + *found = std::move(value); + return found; + } else { + return this->insert(key, std::move(value)); + } + } + int count() { return fMap.count(); } diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp index 868bf6dd13..f14d7dfdee 100644 --- a/src/core/SkRuntimeEffect.cpp +++ b/src/core/SkRuntimeEffect.cpp @@ -15,7 +15,9 @@ #include "src/core/SkColorFilterBase.h" #include "src/core/SkColorSpacePriv.h" #include "src/core/SkColorSpaceXformSteps.h" +#include "src/core/SkLRUCache.h" #include "src/core/SkMatrixProvider.h" +#include "src/core/SkOpts.h" #include "src/core/SkRasterPipeline.h" #include "src/core/SkReadBuffer.h" #include "src/core/SkUtils.h" @@ -125,7 +127,42 @@ static bool init_uniform_type(const SkSL::Context& ctx, return false; } +SK_BEGIN_REQUIRE_DENSE; +struct Key { + uint32_t skslHashA; + uint32_t skslHashB; + int inlineThreshold; + + bool operator==(const Key& that) const { + return this->skslHashA == that.skslHashA + && this->skslHashB == that.skslHashB + && this->inlineThreshold == that.inlineThreshold; + } + + Key(const SkString& sksl, const SkRuntimeEffect::Options& options) + : skslHashA(SkOpts::hash(sksl.c_str(), sksl.size(), 0)) + , skslHashB(SkOpts::hash(sksl.c_str(), sksl.size(), 1)) + , inlineThreshold(options.inlineThreshold) {} +}; +SK_END_REQUIRE_DENSE; + +static SkMutex gCacheLock; + +static SkLRUCache>* cache() { + gCacheLock.assertHeld(); + static auto* cache = new SkLRUCache>(11/*totally arbitrary*/); + return cache; +} + SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl, const Options& options) { + Key key(sksl, options); + { + SkAutoMutexExclusive _(gCacheLock); + if (sk_sp* found = cache()->find(key)) { + return Result{*found, SkString()}; + } + } + SkSL::SharedCompiler compiler; SkSL::Program::Settings settings; settings.fInlineThreshold = options.inlineThreshold; @@ -246,6 +283,10 @@ SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl, const Options& opti std::move(varyings), usesSampleCoords, allowColorFilter)); + { + SkAutoMutexExclusive _(gCacheLock); + cache()->insert_or_update(key, effect); + } return Result{std::move(effect), SkString()}; } diff --git a/src/core/SkVMBlitter.cpp b/src/core/SkVMBlitter.cpp index 2d527c4f6f..e6eed857fe 100644 --- a/src/core/SkVMBlitter.cpp +++ b/src/core/SkVMBlitter.cpp @@ -563,12 +563,7 @@ namespace { if (SkLRUCache* cache = try_acquire_program_cache()) { auto cache_program = [&](skvm::Program&& program, Coverage coverage) { if (!program.empty()) { - Key key = fKey.withCoverage(coverage); - if (skvm::Program* found = cache->find(key)) { - *found = std::move(program); - } else { - cache->insert(key, std::move(program)); - } + cache->insert_or_update(fKey.withCoverage(coverage), std::move(program)); } }; cache_program(std::move(fBlitH), Coverage::Full); diff --git a/src/effects/SkHighContrastFilter.cpp b/src/effects/SkHighContrastFilter.cpp index e8dfc58b02..a0fcd2f924 100644 --- a/src/effects/SkHighContrastFilter.cpp +++ b/src/effects/SkHighContrastFilter.cpp @@ -18,38 +18,35 @@ sk_sp SkHighContrastFilter::Make(const SkHighContrastConfig& conf struct Uniforms { float grayscale, invertStyle, contrast; }; - static SkRuntimeEffect* effect = []{ - SkString code{R"( - uniform shader input; - uniform half grayscale, invertStyle, contrast; - )"}; - code += kRGB_to_HSL_sksl; - code += kHSL_to_RGB_sksl; - code += R"( - half4 main() { - half4 c = sample(input); // linear unpremul RGBA in dst gamut. - if (grayscale == 1) { - c.rgb = dot(half3(0.2126, 0.7152, 0.0722), c.rgb).rrr; - } - if (invertStyle == 1/*brightness*/) { - c.rgb = 1 - c.rgb; - } else if (invertStyle == 2/*lightness*/) { - c.rgb = rgb_to_hsl(c.rgb); - c.b = 1 - c.b; - c.rgb = hsl_to_rgb(c.rgb); - } - c.rgb = mix(half3(0.5), c.rgb, contrast); - return half4(saturate(c.rgb), c.a); + SkString code{R"( + uniform shader input; + uniform half grayscale, invertStyle, contrast; + )"}; + code += kRGB_to_HSL_sksl; + code += kHSL_to_RGB_sksl; + code += R"( + half4 main() { + half4 c = sample(input); // linear unpremul RGBA in dst gamut. + if (grayscale == 1) { + c.rgb = dot(half3(0.2126, 0.7152, 0.0722), c.rgb).rrr; } - )"; - - auto [effect, err] = SkRuntimeEffect::Make(code); - if (!err.isEmpty()) { - SkDebugf("%s\n%s\n", code.c_str(), err.c_str()); + if (invertStyle == 1/*brightness*/) { + c.rgb = 1 - c.rgb; + } else if (invertStyle == 2/*lightness*/) { + c.rgb = rgb_to_hsl(c.rgb); + c.b = 1 - c.b; + c.rgb = hsl_to_rgb(c.rgb); + } + c.rgb = mix(half3(0.5), c.rgb, contrast); + return half4(saturate(c.rgb), c.a); } - SkASSERT(effect && err.isEmpty()); - return effect.release(); - }(); + )"; + + auto [effect, err] = SkRuntimeEffect::Make(code); + if (!err.isEmpty()) { + SkDebugf("%s\n%s\n", code.c_str(), err.c_str()); + } + SkASSERT(effect && err.isEmpty()); // A contrast setting of exactly +1 would divide by zero (1+c)/(1-c), so pull in to +1-ε. // I'm not exactly sure why we've historically pinned -1 up to -1+ε, maybe just symmetry? diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp index df234b1bac..a62432a622 100644 --- a/src/effects/SkLumaColorFilter.cpp +++ b/src/effects/SkLumaColorFilter.cpp @@ -10,17 +10,14 @@ #include "include/effects/SkRuntimeEffect.h" sk_sp SkLumaColorFilter::Make() { - static SkColorFilter* filter = []{ - const char* code = - "uniform shader input;" - "half4 main() {" - "return saturate(dot(half3(0.2126, 0.7152, 0.0722), sample(input).rgb)).000r;" - "}"; - auto [effect, err] = SkRuntimeEffect::Make(SkString{code}, SkRuntimeEffect::Options{}); - SkASSERT(effect && err.isEmpty()); + const char* code = + "uniform shader input;" + "half4 main() {" + "return saturate(dot(half3(0.2126, 0.7152, 0.0722), sample(input).rgb)).000r;" + "}"; + auto [effect, err] = SkRuntimeEffect::Make(SkString{code}); + SkASSERT(effect && err.isEmpty()); - sk_sp input = nullptr; - return effect->makeColorFilter(SkData::MakeEmpty(), &input, 1).release(); - }(); - return sk_ref_sp(filter); + sk_sp input = nullptr; + return effect->makeColorFilter(SkData::MakeEmpty(), &input, 1); }