centralize runtime effect caching
Relative runtimes for creating luma color filter: - cached SkColorFilter --> 1x - cached SkRuntimeEffect --> 12x - no caching --> 186x - this CL --> 24x Added insert_or_update() to SkLRUCache because I keep falling into this trap using insert()... Change-Id: Ic3dad32d38fc001701d8e1ad5662ad382503418f Reviewed-on: https://skia-review.googlesource.com/c/skia/+/376776 Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
6706c9fa14
commit
ef7a28e26a
@ -443,16 +443,13 @@ sk_sp<SkColorFilter> SkColorFilters::Lerp(float weight, sk_sp<SkColorFilter> 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<SkColorFilter> inputs[] = {cf0,cf1};
|
||||
return effect->makeColorFilter(SkData::MakeWithCopy(&weight, sizeof(weight)),
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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<Key, sk_sp<SkRuntimeEffect>>* cache() {
|
||||
gCacheLock.assertHeld();
|
||||
static auto* cache = new SkLRUCache<Key, sk_sp<SkRuntimeEffect>>(11/*totally arbitrary*/);
|
||||
return cache;
|
||||
}
|
||||
|
||||
SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl, const Options& options) {
|
||||
Key key(sksl, options);
|
||||
{
|
||||
SkAutoMutexExclusive _(gCacheLock);
|
||||
if (sk_sp<SkRuntimeEffect>* 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()};
|
||||
}
|
||||
|
||||
|
@ -563,12 +563,7 @@ namespace {
|
||||
if (SkLRUCache<Key, skvm::Program>* 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);
|
||||
|
@ -18,38 +18,35 @@ sk_sp<SkColorFilter> 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?
|
||||
|
@ -10,17 +10,14 @@
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
|
||||
sk_sp<SkColorFilter> 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<SkColorFilter> input = nullptr;
|
||||
return effect->makeColorFilter(SkData::MakeEmpty(), &input, 1).release();
|
||||
}();
|
||||
return sk_ref_sp(filter);
|
||||
sk_sp<SkColorFilter> input = nullptr;
|
||||
return effect->makeColorFilter(SkData::MakeEmpty(), &input, 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user