When converting runtime SkSL to FP SkSL, use default settings

Anything related to caps should be resolved in the second compile.
However, when calling toPipelineStage, the settings stored in the
base Program are used, so we need to inject them at that point.

This also removes the cache of specialized programs. We only hit
that code path when we're about to do a full compile, including
generating SkSL, turning that into GLSL, etc. The specialization
is implicitly cached as part of the entire program for common
cases, so the second level isn't that useful.

Change-Id: I53bc54b0611951e1d97278d59881308c6b152090
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/259162
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Osman 2019-12-11 14:36:23 -05:00 committed by Skia Commit-Bot
parent acf5929ae0
commit 48fcf36e15
4 changed files with 33 additions and 55 deletions

View File

@ -73,7 +73,7 @@ protected:
SkASSERT(caps && !FPFactoryCache); SkASSERT(caps && !FPFactoryCache);
SkASSERT(!fThreadSafeProxy); SkASSERT(!fThreadSafeProxy);
FPFactoryCache.reset(new GrSkSLFPFactoryCache(caps->refShaderCaps())); FPFactoryCache.reset(new GrSkSLFPFactoryCache());
fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(), fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(),
this->options(), this->options(),
this->contextID(), this->contextID(),

View File

@ -11,7 +11,6 @@
#include <vector> #include <vector>
#include "include/core/SkRefCnt.h" #include "include/core/SkRefCnt.h"
class GrShaderCaps;
class GrSkSLFPFactory; class GrSkSLFPFactory;
// This is a cache used by GrSkSLFP to retain GrSkSLFPFactory instances, so we don't have to // This is a cache used by GrSkSLFP to retain GrSkSLFPFactory instances, so we don't have to
@ -21,7 +20,6 @@ class GrSkSLFPFactory;
// onGetGLSLProcessorKey. // onGetGLSLProcessorKey.
class GrSkSLFPFactoryCache : public SkNVRefCnt<GrSkSLFPFactoryCache> { class GrSkSLFPFactoryCache : public SkNVRefCnt<GrSkSLFPFactoryCache> {
public: public:
GrSkSLFPFactoryCache(sk_sp<const GrShaderCaps> shaderCaps) : fShaderCaps(shaderCaps) {}
~GrSkSLFPFactoryCache(); ~GrSkSLFPFactoryCache();
sk_sp<GrSkSLFPFactory> findOrCreate(int index, const char* name, const char* skSL); sk_sp<GrSkSLFPFactory> findOrCreate(int index, const char* name, const char* skSL);
@ -37,7 +35,6 @@ private:
mutable SkMutex fCacheMutex; mutable SkMutex fCacheMutex;
std::vector<sk_sp<GrSkSLFPFactory>> fFactories; std::vector<sk_sp<GrSkSLFPFactory>> fFactories;
sk_sp<const GrShaderCaps> fShaderCaps;
}; };
#endif #endif

View File

@ -18,10 +18,9 @@
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLProgramBuilder.h" #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl) GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const char* sksl)
: fName(name) { : fName(name) {
SkSL::Program::Settings settings; SkSL::Program::Settings settings;
settings.fCaps = shaderCaps;
fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind, fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind,
SkSL::String(sksl), settings); SkSL::String(sksl), settings);
if (fCompiler.errorCount()) { if (fCompiler.errorCount()) {
@ -58,13 +57,8 @@ static std::tuple<const SkSL::Type*, int> strip_array(const SkSL::Type* type) {
return std::make_tuple(type, arrayCount); return std::make_tuple(type, arrayCount);
} }
const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs, std::unique_ptr<SkSL::Program> GrSkSLFPFactory::getSpecialization(const void* inputs,
size_t inputSize) { size_t inputSize) {
const auto& found = fSpecializations.find(key);
if (found != fSpecializations.end()) {
return found->second.get();
}
std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap; std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap;
size_t offset = 0; size_t offset = 0;
for (const auto& v : fInAndUniformVars) { for (const auto& v : fInAndUniformVars) {
@ -116,9 +110,7 @@ const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key,
SkDebugf("%s\n", fCompiler.errorText().c_str()); SkDebugf("%s\n", fCompiler.errorText().c_str());
SkASSERT(false); SkASSERT(false);
} }
const SkSL::Program* result = specialized.get(); return specialized;
fSpecializations.insert(std::make_pair(key, std::move(specialized)));
return result;
} }
static std::tuple<SkSL::Layout::CType, int> get_ctype(const SkSL::Context& context, static std::tuple<SkSL::Layout::CType, int> get_ctype(const SkSL::Context& context,
@ -380,6 +372,7 @@ std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, con
const char* sksl, const void* inputs, size_t inputSize, const char* sksl, const void* inputs, size_t inputSize,
const SkMatrix* matrix) { const SkMatrix* matrix) {
return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(), return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
context->priv().caps()->refShaderCaps(),
index, name, sksl, SkString(), index, name, sksl, SkString(),
inputs, inputSize, matrix)); inputs, inputSize, matrix));
} }
@ -388,16 +381,18 @@ std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, con
SkString sksl, const void* inputs, size_t inputSize, SkString sksl, const void* inputs, size_t inputSize,
const SkMatrix* matrix) { const SkMatrix* matrix) {
return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(), return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
context->priv().caps()->refShaderCaps(),
index, name, nullptr, std::move(sksl), index, name, nullptr, std::move(sksl),
inputs, inputSize, matrix)); inputs, inputSize, matrix));
} }
GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, sk_sp<const GrShaderCaps> shaderCaps,
int index, const char* name, const char* sksl, int index, const char* name, const char* sksl,
SkString skslString, const void* inputs, size_t inputSize, SkString skslString, const void* inputs, size_t inputSize,
const SkMatrix* matrix) const SkMatrix* matrix)
: INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags) : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
, fFactoryCache(factoryCache) , fFactoryCache(factoryCache)
, fShaderCaps(std::move(shaderCaps))
, fIndex(index) , fIndex(index)
, fName(name) , fName(name)
, fSkSLString(skslString) , fSkSLString(skslString)
@ -416,6 +411,7 @@ GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache,
GrSkSLFP::GrSkSLFP(const GrSkSLFP& other) GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
: INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags) : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
, fFactoryCache(other.fFactoryCache) , fFactoryCache(other.fFactoryCache)
, fShaderCaps(other.fShaderCaps)
, fFactory(other.fFactory) , fFactory(other.fFactory)
, fIndex(other.fIndex) , fIndex(other.fIndex)
, fName(other.fName) , fName(other.fName)
@ -448,7 +444,9 @@ void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const { GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
this->createFactory(); this->createFactory();
const SkSL::Program* specialized = fFactory->getSpecialization(fKey, fInputs.get(), fInputSize); auto specialized = fFactory->getSpecialization(fInputs.get(), fInputSize);
specialized->fSettings.fCaps = fShaderCaps.get();
SkSL::String glsl; SkSL::String glsl;
std::vector<SkSL::Compiler::FormatArg> formatArgs; std::vector<SkSL::Compiler::FormatArg> formatArgs;
std::vector<SkSL::Compiler::GLSLFunction> functions; std::vector<SkSL::Compiler::GLSLFunction> functions;
@ -460,19 +458,6 @@ GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
formatArgs, functions); formatArgs, functions);
} }
static void copy_floats_key(char* inputs, GrProcessorKeyBuilder* b, bool isIn, int count,
size_t* offset, SkSL::String* key) {
if (isIn) {
for (size_t i = 0; i < sizeof(float) * count; ++i) {
(*key) += inputs[*offset + i];
b->add32(*(int32_t*) (inputs + *offset));
(*offset) += sizeof(float);
}
} else {
(*offset) += sizeof(float) * count;
}
}
void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const { GrProcessorKeyBuilder* b) const {
this->createFactory(); this->createFactory();
@ -489,7 +474,6 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
switch (ctype) { switch (ctype) {
case SkSL::Layout::CType::kBool: case SkSL::Layout::CType::kBool:
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
fKey += inputs[offset];
b->add32(inputs[offset]); b->add32(inputs[offset]);
} }
++offset; ++offset;
@ -497,10 +481,6 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
case SkSL::Layout::CType::kInt32: { case SkSL::Layout::CType::kInt32: {
offset = SkAlign4(offset); offset = SkAlign4(offset);
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
fKey += inputs[offset + 0];
fKey += inputs[offset + 1];
fKey += inputs[offset + 2];
fKey += inputs[offset + 3];
b->add32(*(int32_t*)(inputs + offset)); b->add32(*(int32_t*)(inputs + offset));
} }
offset += sizeof(int32_t); offset += sizeof(int32_t);
@ -509,28 +489,33 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
case SkSL::Layout::CType::kFloat: { case SkSL::Layout::CType::kFloat: {
offset = SkAlign4(offset); offset = SkAlign4(offset);
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) { if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
fKey += inputs[offset + 0];
fKey += inputs[offset + 1];
fKey += inputs[offset + 2];
fKey += inputs[offset + 3];
b->add32(*(float*)(inputs + offset)); b->add32(*(float*)(inputs + offset));
} }
offset += sizeof(float); offset += sizeof(float);
break; break;
} }
case SkSL::Layout::CType::kFloat2: case SkSL::Layout::CType::kFloat2:
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 2, offset = SkAlign4(offset);
&offset, &fKey); if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
memcpy(b->add32n(2), inputs + offset, 2 * sizeof(float));
}
offset += 2 * sizeof(float);
break; break;
case SkSL::Layout::CType::kFloat3: case SkSL::Layout::CType::kFloat3:
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 3, offset = SkAlign4(offset);
&offset, &fKey); if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
memcpy(b->add32n(3), inputs + offset, 3 * sizeof(float));
}
offset += 3 * sizeof(float);
break; break;
case SkSL::Layout::CType::kSkPMColor: case SkSL::Layout::CType::kSkPMColor:
case SkSL::Layout::CType::kSkPMColor4f: case SkSL::Layout::CType::kSkPMColor4f:
case SkSL::Layout::CType::kSkRect: case SkSL::Layout::CType::kSkRect:
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 4, offset = SkAlign4(offset);
&offset, &fKey); if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
memcpy(b->add32n(4), inputs + offset, 4 * sizeof(float));
}
offset += 4 * sizeof(float);
break; break;
default: default:
// unsupported input var type // unsupported input var type
@ -566,7 +551,7 @@ sk_sp<GrSkSLFPFactory> GrSkSLFPFactoryCache::findOrCreate(int index, const char*
sk_sp<GrSkSLFPFactory> factory = this->get(index); sk_sp<GrSkSLFPFactory> factory = this->get(index);
if (!factory) { if (!factory) {
factory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(name, fShaderCaps.get(), skSL)); factory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(name, skSL));
this->set(index, factory); this->set(index, factory);
} }

View File

@ -110,7 +110,7 @@ public:
std::unique_ptr<GrFragmentProcessor> clone() const override; std::unique_ptr<GrFragmentProcessor> clone() const override;
private: private:
GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, sk_sp<const GrShaderCaps> shaderCaps,
int fIndex, const char* name, const char* sksl, int fIndex, const char* name, const char* sksl,
SkString skslString, const void* inputs, size_t inputSize, const SkMatrix* matrix); SkString skslString, const void* inputs, size_t inputSize, const SkMatrix* matrix);
@ -125,6 +125,7 @@ private:
void createFactory() const; void createFactory() const;
sk_sp<GrSkSLFPFactoryCache> fFactoryCache; sk_sp<GrSkSLFPFactoryCache> fFactoryCache;
sk_sp<const GrShaderCaps> fShaderCaps;
mutable sk_sp<GrSkSLFPFactory> fFactory; mutable sk_sp<GrSkSLFPFactory> fFactory;
@ -148,8 +149,6 @@ private:
GrCoordTransform fCoordTransform; GrCoordTransform fCoordTransform;
mutable SkSL::String fKey;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST GR_DECLARE_FRAGMENT_PROCESSOR_TEST
typedef GrFragmentProcessor INHERITED; typedef GrFragmentProcessor INHERITED;
@ -172,10 +171,9 @@ public:
* the produced shaders to differ), so it is important to reuse the same factory instance for * the produced shaders to differ), so it is important to reuse the same factory instance for
* the same shader in order to avoid repeatedly re-parsing the SkSL. * the same shader in order to avoid repeatedly re-parsing the SkSL.
*/ */
GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl); GrSkSLFPFactory(const char* name, const char* sksl);
const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs, std::unique_ptr<SkSL::Program> getSpecialization(const void* inputs, size_t inputSize);
size_t inputSize);
const char* fName; const char* fName;
@ -185,8 +183,6 @@ public:
std::vector<const SkSL::Variable*> fInAndUniformVars; std::vector<const SkSL::Variable*> fInAndUniformVars;
std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations;
friend class GrSkSLFP; friend class GrSkSLFP;
}; };