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(!fThreadSafeProxy);
FPFactoryCache.reset(new GrSkSLFPFactoryCache(caps->refShaderCaps()));
FPFactoryCache.reset(new GrSkSLFPFactoryCache());
fThreadSafeProxy = GrContextThreadSafeProxyPriv::Make(this->backend(),
this->options(),
this->contextID(),

View File

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

View File

@ -18,10 +18,9 @@
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.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) {
SkSL::Program::Settings settings;
settings.fCaps = shaderCaps;
fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind,
SkSL::String(sksl), settings);
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);
}
const SkSL::Program* GrSkSLFPFactory::getSpecialization(const SkSL::String& key, const void* inputs,
size_t inputSize) {
const auto& found = fSpecializations.find(key);
if (found != fSpecializations.end()) {
return found->second.get();
}
std::unique_ptr<SkSL::Program> GrSkSLFPFactory::getSpecialization(const void* inputs,
size_t inputSize) {
std::unordered_map<SkSL::String, SkSL::Program::Settings::Value> inputMap;
size_t offset = 0;
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());
SkASSERT(false);
}
const SkSL::Program* result = specialized.get();
fSpecializations.insert(std::make_pair(key, std::move(specialized)));
return result;
return specialized;
}
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 SkMatrix* matrix) {
return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
context->priv().caps()->refShaderCaps(),
index, name, sksl, SkString(),
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,
const SkMatrix* matrix) {
return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
context->priv().caps()->refShaderCaps(),
index, name, nullptr, std::move(sksl),
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,
SkString skslString, const void* inputs, size_t inputSize,
const SkMatrix* matrix)
: INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
, fFactoryCache(factoryCache)
, fShaderCaps(std::move(shaderCaps))
, fIndex(index)
, fName(name)
, fSkSLString(skslString)
@ -416,6 +411,7 @@ GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache,
GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
: INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
, fFactoryCache(other.fFactoryCache)
, fShaderCaps(other.fShaderCaps)
, fFactory(other.fFactory)
, fIndex(other.fIndex)
, fName(other.fName)
@ -448,7 +444,9 @@ void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
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;
std::vector<SkSL::Compiler::FormatArg> formatArgs;
std::vector<SkSL::Compiler::GLSLFunction> functions;
@ -460,19 +458,6 @@ GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
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,
GrProcessorKeyBuilder* b) const {
this->createFactory();
@ -489,7 +474,6 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
switch (ctype) {
case SkSL::Layout::CType::kBool:
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
fKey += inputs[offset];
b->add32(inputs[offset]);
}
++offset;
@ -497,10 +481,6 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
case SkSL::Layout::CType::kInt32: {
offset = SkAlign4(offset);
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));
}
offset += sizeof(int32_t);
@ -509,28 +489,33 @@ void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
case SkSL::Layout::CType::kFloat: {
offset = SkAlign4(offset);
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));
}
offset += sizeof(float);
break;
}
case SkSL::Layout::CType::kFloat2:
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 2,
&offset, &fKey);
offset = SkAlign4(offset);
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
memcpy(b->add32n(2), inputs + offset, 2 * sizeof(float));
}
offset += 2 * sizeof(float);
break;
case SkSL::Layout::CType::kFloat3:
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 3,
&offset, &fKey);
offset = SkAlign4(offset);
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
memcpy(b->add32n(3), inputs + offset, 3 * sizeof(float));
}
offset += 3 * sizeof(float);
break;
case SkSL::Layout::CType::kSkPMColor:
case SkSL::Layout::CType::kSkPMColor4f:
case SkSL::Layout::CType::kSkRect:
copy_floats_key(inputs, b, v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag, 4,
&offset, &fKey);
offset = SkAlign4(offset);
if (v->fModifiers.fFlags & SkSL::Modifiers::kIn_Flag) {
memcpy(b->add32n(4), inputs + offset, 4 * sizeof(float));
}
offset += 4 * sizeof(float);
break;
default:
// unsupported input var type
@ -566,7 +551,7 @@ sk_sp<GrSkSLFPFactory> GrSkSLFPFactoryCache::findOrCreate(int index, const char*
sk_sp<GrSkSLFPFactory> factory = this->get(index);
if (!factory) {
factory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(name, fShaderCaps.get(), skSL));
factory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(name, skSL));
this->set(index, factory);
}

View File

@ -110,7 +110,7 @@ public:
std::unique_ptr<GrFragmentProcessor> clone() const override;
private:
GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache,
GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, sk_sp<const GrShaderCaps> shaderCaps,
int fIndex, const char* name, const char* sksl,
SkString skslString, const void* inputs, size_t inputSize, const SkMatrix* matrix);
@ -125,6 +125,7 @@ private:
void createFactory() const;
sk_sp<GrSkSLFPFactoryCache> fFactoryCache;
sk_sp<const GrShaderCaps> fShaderCaps;
mutable sk_sp<GrSkSLFPFactory> fFactory;
@ -148,8 +149,6 @@ private:
GrCoordTransform fCoordTransform;
mutable SkSL::String fKey;
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
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 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,
size_t inputSize);
std::unique_ptr<SkSL::Program> getSpecialization(const void* inputs, size_t inputSize);
const char* fName;
@ -185,8 +183,6 @@ public:
std::vector<const SkSL::Variable*> fInAndUniformVars;
std::unordered_map<SkSL::String, std::unique_ptr<const SkSL::Program>> fSpecializations;
friend class GrSkSLFP;
};