converted arithmetic FP to new FP structure
Bug: skia:
Change-Id: I5492b378fa0f2ab7b453b2b1b18e4aef898370d2
Reviewed-on: https://skia-review.googlesource.com/148910
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index b92b6cd..a0d010f 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -332,8 +332,6 @@
"$_src/gpu/effects/GrAARectEffect.h",
"$_src/gpu/effects/GrAlphaThresholdFragmentProcessor.cpp",
"$_src/gpu/effects/GrAlphaThresholdFragmentProcessor.h",
- "$_src/gpu/effects/GrArithmeticFP.cpp",
- "$_src/gpu/effects/GrArithmeticFP.h",
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.cpp",
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.h",
"$_src/gpu/effects/GrCircleBlurFragmentProcessor.cpp",
diff --git a/gn/sksl.gni b/gn/sksl.gni
index fa04c8e..aae7e26 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -31,7 +31,6 @@
skia_gpu_processor_sources = [
"$_src/gpu/effects/GrAARectEffect.fp",
"$_src/gpu/effects/GrAlphaThresholdFragmentProcessor.fp",
- "$_src/gpu/effects/GrArithmeticFP.fp",
"$_src/gpu/effects/GrBlurredEdgeFragmentProcessor.fp",
"$_src/gpu/effects/GrCircleBlurFragmentProcessor.fp",
"$_src/gpu/effects/GrCircleEffect.fp",
diff --git a/include/effects/SkArithmeticImageFilter.h b/include/effects/SkArithmeticImageFilter.h
index 40b91e8..7f4aea1 100644
--- a/include/effects/SkArithmeticImageFilter.h
+++ b/include/effects/SkArithmeticImageFilter.h
@@ -10,6 +10,13 @@
#include "SkImageFilter.h"
+extern const char* SKSL_ARITHMETIC_SRC;
+
+struct ArithmeticFPInputs {
+ float k[4];
+ bool enforcePMColor;
+};
+
class SK_API SkArithmeticImageFilter {
public:
static sk_sp<SkImageFilter> Make(float k1, float k2, float k3, float k4, bool enforcePMColor,
diff --git a/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
index 644494e..2e5b801 100644
--- a/src/effects/imagefilters/SkArithmeticImageFilter.cpp
+++ b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
@@ -22,8 +22,8 @@
#include "GrRenderTargetContext.h"
#include "GrTextureProxy.h"
#include "SkGr.h"
-#include "effects/GrArithmeticFP.h"
#include "effects/GrConstColorProcessor.h"
+#include "effects/GrSkSLFP.h"
#include "effects/GrTextureDomain.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
@@ -31,6 +31,20 @@
#include "glsl/GrGLSLUniformHandler.h"
#endif
+const char* SKSL_ARITHMETIC_SRC = R"(
+in uniform float4 k;
+layout(key) const in bool enforcePMColor;
+in fragmentProcessor child;
+
+void main(int x, int y, inout half4 color) {
+ half4 dst = process(child);
+ color = saturate(k.x * color * dst + k.y * color + k.z * dst + k.w);
+ if (enforcePMColor) {
+ color.rgb = min(color.rgb, color.a);
+ }
+}
+)";
+
class ArithmeticImageFilterImpl : public SkImageFilter {
public:
ArithmeticImageFilterImpl(float k1, float k2, float k3, float k4, bool enforcePMColor,
@@ -268,21 +282,6 @@
#if SK_SUPPORT_GPU
-#if GR_TEST_UTILS
-std::unique_ptr<GrFragmentProcessor> GrArithmeticFP::TestCreate(GrProcessorTestData* d) {
- float k1 = d->fRandom->nextF();
- float k2 = d->fRandom->nextF();
- float k3 = d->fRandom->nextF();
- float k4 = d->fRandom->nextF();
- bool enforcePMColor = d->fRandom->nextBool();
-
- std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
- return GrArithmeticFP::Make(k1, k2, k3, k4, enforcePMColor, std::move(dst));
-}
-#endif
-
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrArithmeticFP);
-
sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
SkSpecialImage* source,
sk_sp<SkSpecialImage> background,
@@ -336,11 +335,19 @@
outputProperties.colorSpace());
paint.addColorFragmentProcessor(std::move(foregroundFP));
- std::unique_ptr<GrFragmentProcessor> xferFP =
- GrArithmeticFP::Make(fK[0], fK[1], fK[2], fK[3], fEnforcePMColor, std::move(bgFP));
-
- // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
+ static int arithmeticIndex = GrSkSLFP::NewIndex();
+ ArithmeticFPInputs inputs;
+ static_assert(sizeof(inputs.k) == sizeof(fK), "struct size mismatch");
+ memcpy(inputs.k, fK, sizeof(inputs.k));
+ inputs.enforcePMColor = fEnforcePMColor;
+ std::unique_ptr<GrFragmentProcessor> xferFP = GrSkSLFP::Make(context,
+ arithmeticIndex,
+ "Arithmetic",
+ SKSL_ARITHMETIC_SRC,
+ &inputs,
+ sizeof(inputs));
if (xferFP) {
+ ((GrSkSLFP&) *xferFP).addChild(std::move(bgFP));
paint.addColorFragmentProcessor(std::move(xferFP));
}
} else {
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index aba8d9b..aafe1d8 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -57,7 +57,7 @@
* we verify the count is as expected. If a new factory is added, then these numbers must be
* manually adjusted.
*/
-static const int kFPFactoryCount = 37;
+static const int kFPFactoryCount = 36;
static const int kGPFactoryCount = 14;
static const int kXPFactoryCount = 4;
diff --git a/src/gpu/effects/GrArithmeticFP.cpp b/src/gpu/effects/GrArithmeticFP.cpp
deleted file mode 100644
index b7d37a8..0000000
--- a/src/gpu/effects/GrArithmeticFP.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**************************************************************************************************
- *** This file was autogenerated from GrArithmeticFP.fp; do not modify.
- **************************************************************************************************/
-#include "GrArithmeticFP.h"
-#include "glsl/GrGLSLFragmentProcessor.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "glsl/GrGLSLProgramBuilder.h"
-#include "GrTexture.h"
-#include "SkSLCPP.h"
-#include "SkSLUtil.h"
-class GrGLSLArithmeticFP : public GrGLSLFragmentProcessor {
-public:
- GrGLSLArithmeticFP() {}
- void emitCode(EmitArgs& args) override {
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- const GrArithmeticFP& _outer = args.fFp.cast<GrArithmeticFP>();
- (void)_outer;
- auto k1 = _outer.k1();
- (void)k1;
- auto k2 = _outer.k2();
- (void)k2;
- auto k3 = _outer.k3();
- (void)k3;
- auto k4 = _outer.k4();
- (void)k4;
- auto enforcePMColor = _outer.enforcePMColor();
- (void)enforcePMColor;
- fKVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
- kDefault_GrSLPrecision, "k");
- SkString _child0("_child0");
- this->emitChild(0, &_child0, args);
- fragBuilder->codeAppendf(
- "half4 dst = %s;\n%s = half4(clamp(float4(float4(((%s.x * float4(%s)) * dst + %s.y "
- "* float4(%s)) + %s.z * float4(dst)) + %s.w), 0.0, 1.0));\nif (%s) {\n %s.xyz = "
- "half3(min(float3(%s.xyz), float(%s.w)));\n}\n",
- _child0.c_str(), args.fOutputColor, args.fUniformHandler->getUniformCStr(fKVar),
- args.fInputColor ? args.fInputColor : "half4(1)",
- args.fUniformHandler->getUniformCStr(fKVar),
- args.fInputColor ? args.fInputColor : "half4(1)",
- args.fUniformHandler->getUniformCStr(fKVar),
- args.fUniformHandler->getUniformCStr(fKVar),
- (_outer.enforcePMColor() ? "true" : "false"), args.fOutputColor, args.fOutputColor,
- args.fOutputColor);
- }
-
-private:
- void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& _proc) override {
- const GrArithmeticFP& _outer = _proc.cast<GrArithmeticFP>();
- auto k1 = _outer.k1();
- (void)k1;
- auto k2 = _outer.k2();
- (void)k2;
- auto k3 = _outer.k3();
- (void)k3;
- auto k4 = _outer.k4();
- (void)k4;
- auto enforcePMColor = _outer.enforcePMColor();
- (void)enforcePMColor;
- UniformHandle& k = fKVar;
- (void)k;
-
- pdman.set4f(k, k1, k2, k3, k4);
- }
- UniformHandle fKVar;
-};
-GrGLSLFragmentProcessor* GrArithmeticFP::onCreateGLSLInstance() const {
- return new GrGLSLArithmeticFP();
-}
-void GrArithmeticFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
- GrProcessorKeyBuilder* b) const {
- b->add32((int32_t)fEnforcePMColor);
-}
-bool GrArithmeticFP::onIsEqual(const GrFragmentProcessor& other) const {
- const GrArithmeticFP& that = other.cast<GrArithmeticFP>();
- (void)that;
- if (fK1 != that.fK1) return false;
- if (fK2 != that.fK2) return false;
- if (fK3 != that.fK3) return false;
- if (fK4 != that.fK4) return false;
- if (fEnforcePMColor != that.fEnforcePMColor) return false;
- return true;
-}
-GrArithmeticFP::GrArithmeticFP(const GrArithmeticFP& src)
- : INHERITED(kGrArithmeticFP_ClassID, src.optimizationFlags())
- , fK1(src.fK1)
- , fK2(src.fK2)
- , fK3(src.fK3)
- , fK4(src.fK4)
- , fEnforcePMColor(src.fEnforcePMColor) {
- this->registerChildProcessor(src.childProcessor(0).clone());
-}
-std::unique_ptr<GrFragmentProcessor> GrArithmeticFP::clone() const {
- return std::unique_ptr<GrFragmentProcessor>(new GrArithmeticFP(*this));
-}
diff --git a/src/gpu/effects/GrArithmeticFP.fp b/src/gpu/effects/GrArithmeticFP.fp
deleted file mode 100644
index ce16b91..0000000
--- a/src/gpu/effects/GrArithmeticFP.fp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-in float k1;
-in float k2;
-in float k3;
-in float k4;
-layout(key) in bool enforcePMColor;
-in fragmentProcessor child;
-
-uniform float4 k;
-
-void main() {
- half4 dst = process(child);
- sk_OutColor = saturate(k.x * sk_InColor * dst + k.y * sk_InColor + k.z * dst + k.w);
- if (enforcePMColor) {
- sk_OutColor.rgb = min(sk_OutColor.rgb, sk_OutColor.a);
- }
-}
-
-@setData(pdman) {
- pdman.set4f(k, k1, k2, k3, k4);
-}
diff --git a/src/gpu/effects/GrArithmeticFP.h b/src/gpu/effects/GrArithmeticFP.h
deleted file mode 100644
index 7debf26..0000000
--- a/src/gpu/effects/GrArithmeticFP.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**************************************************************************************************
- *** This file was autogenerated from GrArithmeticFP.fp; do not modify.
- **************************************************************************************************/
-#ifndef GrArithmeticFP_DEFINED
-#define GrArithmeticFP_DEFINED
-#include "SkTypes.h"
-#include "GrFragmentProcessor.h"
-#include "GrCoordTransform.h"
-class GrArithmeticFP : public GrFragmentProcessor {
-public:
- float k1() const { return fK1; }
- float k2() const { return fK2; }
- float k3() const { return fK3; }
- float k4() const { return fK4; }
- bool enforcePMColor() const { return fEnforcePMColor; }
- static std::unique_ptr<GrFragmentProcessor> Make(float k1, float k2, float k3, float k4,
- bool enforcePMColor,
- std::unique_ptr<GrFragmentProcessor> child) {
- return std::unique_ptr<GrFragmentProcessor>(
- new GrArithmeticFP(k1, k2, k3, k4, enforcePMColor, std::move(child)));
- }
- GrArithmeticFP(const GrArithmeticFP& src);
- std::unique_ptr<GrFragmentProcessor> clone() const override;
- const char* name() const override { return "ArithmeticFP"; }
-
-private:
- GrArithmeticFP(float k1, float k2, float k3, float k4, bool enforcePMColor,
- std::unique_ptr<GrFragmentProcessor> child)
- : INHERITED(kGrArithmeticFP_ClassID, kNone_OptimizationFlags)
- , fK1(k1)
- , fK2(k2)
- , fK3(k3)
- , fK4(k4)
- , fEnforcePMColor(enforcePMColor) {
- this->registerChildProcessor(std::move(child));
- }
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
- bool onIsEqual(const GrFragmentProcessor&) const override;
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
- float fK1;
- float fK2;
- float fK3;
- float fK4;
- bool fEnforcePMColor;
- typedef GrFragmentProcessor INHERITED;
-};
-#endif
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index bc84c83..0ebd5c4 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -9,9 +9,11 @@
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
+#include "GrConstColorProcessor.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrTexture.h"
+#include "SkArithmeticImageFilter.h"
#include "SkSLUtil.h"
GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl)
@@ -58,9 +60,20 @@
int32_t v = *(int32_t*) (((uint8_t*) inputs) + offset);
inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
offset += sizeof(int32_t);
+ } else if (&v->fType == fCompiler.context().fBool_Type.get()) {
+ bool v = *(((bool*) inputs) + offset);
+ inputMap.insert(std::make_pair(name, SkSL::Program::Settings::Value(v)));
+ offset += sizeof(bool);
+ } else if (&v->fType == fCompiler.context().fFloat4_Type.get()) {
+ SkASSERT(v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag);
+ offset = SkAlign4(offset) + sizeof(float) * 4;
+ } else if (&v->fType == fCompiler.context().fFragmentProcessor_Type.get()) {
+ // do nothing
+ } else {
+ printf("can't handle input var: %s\n", SkSL::String(v->fType.fName).c_str());
+ SkASSERT(false);
}
}
- SkASSERT(offset == inputSize);
std::unique_ptr<SkSL::Program> specialized = fCompiler.specialize(*fBaseProgram, inputMap);
SkAssertResult(fCompiler.optimize(*specialized));
@@ -71,11 +84,56 @@
class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
public:
- GrGLSLSkSLFP(SkSL::String glsl, std::vector<SkSL::Compiler::FormatArg> formatArgs)
- : fGLSL(glsl)
+ GrGLSLSkSLFP(const SkSL::Context* context, const std::vector<const SkSL::Variable*>* inputVars,
+ SkSL::String glsl, std::vector<SkSL::Compiler::FormatArg> formatArgs)
+ : fContext(*context)
+ , fInputVars(*inputVars)
+ , fGLSL(glsl)
, fFormatArgs(formatArgs) {}
+ GrSLType uniformType(const SkSL::Type& type) {
+ if (type == *fContext.fFloat_Type) {
+ return kFloat_GrSLType;
+ } else if (type == *fContext.fHalf_Type) {
+ return kHalf_GrSLType;
+ } else if (type == *fContext.fFloat2_Type) {
+ return kFloat2_GrSLType;
+ } else if (type == *fContext.fHalf2_Type) {
+ return kHalf2_GrSLType;
+ } else if (type == *fContext.fFloat4_Type) {
+ return kFloat4_GrSLType;
+ } else if (type == *fContext.fHalf4_Type) {
+ return kHalf4_GrSLType;
+ } else if (type == *fContext.fFloat4x4_Type) {
+ return kFloat4x4_GrSLType;
+ } else if (type == *fContext.fHalf4x4_Type) {
+ return kHalf4x4_GrSLType;
+ } else if (type == *fContext.fBool_Type) {
+ return kBool_GrSLType;
+ } else if (type == *fContext.fInt_Type) {
+ return kInt_GrSLType;
+ }
+ printf("%s\n", SkSL::String(type.fName).c_str());
+ SK_ABORT("unsupported uniform type");
+ return kFloat_GrSLType;
+ }
+
void emitCode(EmitArgs& args) override {
+ for (const auto& v : fInputVars) {
+ if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag && v->fType !=
+ *fContext.fFragmentProcessor_Type) {
+ fUniformHandles.push_back(args.fUniformHandler->addUniform(
+ kFragment_GrShaderFlag,
+ this->uniformType(v->fType),
+ kDefault_GrSLPrecision,
+ SkSL::String(v->fName).c_str()));
+ }
+ }
+ std::vector<SkString> childNames;
+ for (int i = 0; i < this->numChildProcessors(); ++i) {
+ childNames.push_back(SkStringPrintf("_child%d", i));
+ this->emitChild(i, &childNames[i], args);
+ }
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
int substringStartIndex = 0;
int formatArgIndex = 0;
@@ -87,17 +145,26 @@
++i;
c = fGLSL[i];
switch (c) {
- case 's':
- switch (fFormatArgs[formatArgIndex++]) {
- case SkSL::Compiler::FormatArg::kInput:
+ case 's': {
+ SkSL::Compiler::FormatArg& arg = fFormatArgs[formatArgIndex++];
+ switch (arg.fKind) {
+ case SkSL::Compiler::FormatArg::Kind::kInput:
fragBuilder->codeAppend(args.fInputColor ? args.fInputColor
: "half4(1)");
break;
- case SkSL::Compiler::FormatArg::kOutput:
+ case SkSL::Compiler::FormatArg::Kind::kOutput:
fragBuilder->codeAppend(args.fOutputColor);
break;
+ case SkSL::Compiler::FormatArg::Kind::kUniform:
+ fragBuilder->codeAppend(args.fUniformHandler->getUniformCStr(
+ fUniformHandles[arg.fIndex]));
+ break;
+ case SkSL::Compiler::FormatArg::Kind::kChildProcessor:
+ fragBuilder->codeAppend(childNames[arg.fIndex].c_str());
+ break;
}
break;
+ }
default:
fragBuilder->codeAppendf("%c", c);
}
@@ -108,21 +175,51 @@
fGLSL.length() - substringStartIndex);
}
+ void onSetData(const GrGLSLProgramDataManager& pdman,
+ const GrFragmentProcessor& _proc) override {
+ size_t uniformIndex = 0;
+ size_t offset = 0;
+ const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
+ char* inputs = (char*) outer.fInputs.get();
+ const SkSL::Context& context = outer.fFactory->fCompiler.context();
+ for (const auto& v : outer.fFactory->fInputVars) {
+ if (&v->fType == context.fFloat4_Type.get()) {
+ offset = SkAlign4(offset);
+ float f1 = *(float*) (inputs + offset);
+ offset += sizeof(float);
+ float f2 = *(float*) (inputs + offset);
+ offset += sizeof(float);
+ float f3 = *(float*) (inputs + offset);
+ offset += sizeof(float);
+ float f4 = *(float*) (inputs + offset);
+ offset += sizeof(float);
+ if (v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
+ pdman.set4f(fUniformHandles[uniformIndex++], f1, f2, f3, f4);
+ }
+ }
+ if (&v->fType == context.fBool_Type.get()) {
+ SkASSERT(!(v->fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag));
+ ++offset;
+ }
+ }
+ }
+
+ const SkSL::Context& fContext;
+ const std::vector<const SkSL::Variable*>& fInputVars;
// nearly-finished GLSL; still contains printf-style "%s" format tokens
const SkSL::String fGLSL;
std::vector<SkSL::Compiler::FormatArg> fFormatArgs;
+ std::vector<UniformHandle> fUniformHandles;
};
-std::unique_ptr<GrFragmentProcessor> GrSkSLFP::Make(GrContext* context, int index, const char* name,
- const char* sksl, const void* inputs,
- size_t inputSize) {
- return std::unique_ptr<GrFragmentProcessor>(new GrSkSLFP(
- context->contextPriv().getFPFactoryCache(),
- context->contextPriv().caps()->shaderCaps(),
- index, name, sksl, inputs, inputSize));
+std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext* context, int index, const char* name,
+ const char* sksl, const void* inputs,
+ size_t inputSize) {
+ return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->contextPriv().getFPFactoryCache(),
+ context->contextPriv().caps()->shaderCaps(),
+ index, name, sksl, inputs, inputSize));
}
-
GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
int index, const char* name, const char* sksl, const void* inputs,
size_t inputSize)
@@ -164,16 +261,20 @@
}
}
+void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
+ this->registerChildProcessor(std::move(child));
+}
+
GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
this->createFactory();
const SkSL::Program* specialized = fFactory->getSpecialization(fKey, fInputs.get(), fInputSize);
SkSL::String glsl;
std::vector<SkSL::Compiler::FormatArg> formatArgs;
- if (!fFactory->fCompiler.toPipelineStage(*specialized, &glsl, &formatArgs)) {
+ if (!fFactory->fCompiler.toPipelineStage(*specialized, &glsl, &formatArgs)) {
printf("%s\n", fFactory->fCompiler.errorText().c_str());
- abort();
+ SkASSERT(false);
}
- return new GrGLSLSkSLFP(glsl, formatArgs);
+ return new GrGLSLSkSLFP(specialized->fContext.get(), &fFactory->fInputVars, glsl, formatArgs);
}
void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
@@ -181,8 +282,9 @@
this->createFactory();
size_t offset = 0;
char* inputs = (char*) fInputs.get();
+ const SkSL::Context& context = fFactory->fCompiler.context();
for (const auto& v : fFactory->fInputVars) {
- if (&v->fType == fFactory->fCompiler.context().fInt_Type.get()) {
+ if (&v->fType == context.fInt_Type.get()) {
offset = SkAlign4(offset);
if (v->fModifiers.fLayout.fKey) {
fKey += inputs[offset + 0];
@@ -192,13 +294,36 @@
b->add32(*(int32_t*) (inputs + offset));
}
offset += sizeof(int32_t);
- }
- else {
+ } else if (&v->fType == context.fFloat4_Type.get()) {
+ if (v->fModifiers.fLayout.fKey) {
+ for (size_t i = 0; i < sizeof(float) * 4; ++i) {
+ fKey += inputs[offset + i];
+ }
+ b->add32(*(int32_t*) (inputs + offset));
+ offset += sizeof(float);
+ b->add32(*(int32_t*) (inputs + offset));
+ offset += sizeof(float);
+ b->add32(*(int32_t*) (inputs + offset));
+ offset += sizeof(float);
+ b->add32(*(int32_t*) (inputs + offset));
+ offset += sizeof(float);
+ } else {
+ offset += sizeof(float) * 4;
+ }
+ } else if (&v->fType == context.fBool_Type.get()) {
+ if (v->fModifiers.fLayout.fKey) {
+ fKey += inputs[offset];
+ b->add32(inputs[offset]);
+ }
+ ++offset;
+ } else if (&v->fType == context.fFragmentProcessor_Type.get()) {
+ continue;
+ } else {
// unsupported input var type
+ printf("%s\n", SkSL::String(v->fType.fName).c_str());
SkASSERT(false);
}
}
- SkASSERT(offset == fInputSize);
}
bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const {
@@ -209,7 +334,11 @@
}
std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
- return std::unique_ptr<GrFragmentProcessor>(new GrSkSLFP(*this));
+ std::unique_ptr<GrSkSLFP> result(new GrSkSLFP(*this));
+ for (int i = 0; i < this->numChildProcessors(); ++i) {
+ result->registerChildProcessor(this->childProcessor(i).clone());
+ }
+ return std::unique_ptr<GrFragmentProcessor>(result.release());
}
// We have to do a bit of manual refcounting in the cache methods below. Ideally, we could just
@@ -222,7 +351,7 @@
return nullptr;
}
GrSkSLFPFactory* result = fFactories[index];
- result->ref();
+ SkSafeRef(result);
return sk_sp<GrSkSLFPFactory>(result);
}
@@ -252,13 +381,31 @@
using Value = SkSL::Program::Settings::Value;
std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
- int type = d->fRandom->nextULessThan(1);
+ int type = d->fRandom->nextULessThan(2);
switch (type) {
case 0: {
static int ditherIndex = NewIndex();
int rangeType = d->fRandom->nextULessThan(3);
- return GrSkSLFP::Make(d->context(), ditherIndex, "Dither", SKSL_DITHER_SRC, &rangeType,
- sizeof(rangeType));
+ std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), ditherIndex, "Dither",
+ SKSL_DITHER_SRC, &rangeType,
+ sizeof(rangeType));
+ return std::unique_ptr<GrFragmentProcessor>(result.release());
+ }
+ case 1: {
+ static int arithmeticIndex = NewIndex();
+ ArithmeticFPInputs inputs;
+ inputs.k[0] = d->fRandom->nextF();
+ inputs.k[1] = d->fRandom->nextF();
+ inputs.k[2] = d->fRandom->nextF();
+ inputs.k[3] = d->fRandom->nextF();
+ inputs.enforcePMColor = d->fRandom->nextBool();
+ std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(d->context(), arithmeticIndex,
+ "Arithmetic", SKSL_ARITHMETIC_SRC,
+ &inputs, sizeof(inputs));
+ result->addChild(GrConstColorProcessor::Make(
+ GrColor4f::OpaqueWhite(),
+ GrConstColorProcessor::InputMode::kIgnore));
+ return std::unique_ptr<GrFragmentProcessor>(result.release());
}
}
SK_ABORT("unreachable");
diff --git a/src/gpu/effects/GrSkSLFP.h b/src/gpu/effects/GrSkSLFP.h
index 428e089..f89e9bf 100644
--- a/src/gpu/effects/GrSkSLFP.h
+++ b/src/gpu/effects/GrSkSLFP.h
@@ -60,7 +60,7 @@
* 'NewIndex()'. Each given SkSL string should have a single, statically defined index
* associated with it.
*/
- static std::unique_ptr<GrFragmentProcessor> Make(
+ static std::unique_ptr<GrSkSLFP> Make(
GrContext* context,
int index,
const char* name,
@@ -70,6 +70,8 @@
const char* name() const override;
+ void addChild(std::unique_ptr<GrFragmentProcessor> child);
+
std::unique_ptr<GrFragmentProcessor> clone() const override;
private:
@@ -108,6 +110,8 @@
typedef GrFragmentProcessor INHERITED;
+ friend class GrGLSLSkSLFP;
+
friend class GrSkSLFPFactory;
};
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 339da2b..cd70278 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -63,9 +63,24 @@
kPermitInvalidStaticTests_Flag = 1,
};
- enum class FormatArg {
- kInput,
- kOutput
+ struct FormatArg {
+ enum class Kind {
+ kInput,
+ kOutput,
+ kUniform,
+ kChildProcessor
+ };
+
+ FormatArg(Kind kind)
+ : fKind(kind) {}
+
+ FormatArg(Kind kind, int index)
+ : fKind(kind)
+ , fIndex(index) {}
+
+ Kind fKind;
+
+ int fIndex;
};
Compiler(Flags flags = kNone_Flags);
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 5d4e5c3..65fdbaf 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -1987,7 +1987,6 @@
std::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) const {
auto found = fSettings->fArgs.find(name);
if (found == fSettings->fArgs.end()) {
- fErrors.error(offset, "unknown argument '" + name + "'");
return nullptr;
}
String fullName = "sk_Args." + name;
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
index aceb75e..4ca839d 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -76,6 +76,39 @@
}
}
+void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
+ if (c.fFunction.fBuiltin && c.fFunction.fName == "process") {
+ SkASSERT(c.fArguments.size() == 1);
+ SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind);
+ int index = 0;
+ bool found = false;
+ for (const auto& p : fProgram) {
+ if (ProgramElement::kVar_Kind == p.fKind) {
+ const VarDeclarations& decls = (const VarDeclarations&) p;
+ for (const auto& raw : decls.fVars) {
+ VarDeclaration& decl = (VarDeclaration&) *raw;
+ if (decl.fVar == &((VariableReference&) *c.fArguments[0]).fVariable) {
+ found = true;
+ } else if (decl.fVar->fType == *fContext.fFragmentProcessor_Type) {
+ ++index;
+ }
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+ SkASSERT(found);
+ fExtraEmitCodeCode += " this->emitChild(" + to_string(index) + ", fChildren[" +
+ to_string(index) + "], args);\n";
+ this->write("%s");
+ fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor,
+ index));
+ return;
+ }
+ INHERITED::writeFunctionCall(c);
+}
+
void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) {
this->write(to_string((int32_t) i.fValue));
}
@@ -84,11 +117,11 @@
switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
case SK_INCOLOR_BUILTIN:
this->write("%s");
- fFormatArgs->push_back(Compiler::FormatArg::kInput);
+ fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
break;
case SK_OUTCOLOR_BUILTIN:
this->write("%s");
- fFormatArgs->push_back(Compiler::FormatArg::kOutput);
+ fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
break;
case SK_MAIN_X_BUILTIN:
this->write("sk_FragCoord.x");
@@ -97,7 +130,36 @@
this->write("sk_FragCoord.y");
break;
default:
- this->write(ref.fVariable.fName);
+ if (ref.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag) {
+ this->write("%s");
+ int index = 0;
+ bool found = false;
+ for (const auto& e : fProgram) {
+ if (found) {
+ break;
+ }
+ if (e.fKind == ProgramElement::Kind::kVar_Kind) {
+ const VarDeclarations& decls = (const VarDeclarations&) e;
+ for (const auto& decl : decls.fVars) {
+ const Variable& var = *((VarDeclaration&) *decl).fVar;
+ if (&var == &ref.fVariable) {
+ found = true;
+ break;
+ }
+ if (var.fModifiers.fFlags & (Modifiers::kIn_Flag |
+ Modifiers::kUniform_Flag)) {
+ ++index;
+ }
+ }
+ }
+ }
+ SkASSERT(found);
+ fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
+ index));
+ }
+ else {
+ this->write(ref.fVariable.fName);
+ }
}
}
@@ -122,8 +184,8 @@
StringStream buffer;
fOut = &buffer;
this->write("%s = %s;\n");
- fFormatArgs->push_back(Compiler::FormatArg::kOutput);
- fFormatArgs->push_back(Compiler::FormatArg::kInput);
+ fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
+ fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kInput));
for (const auto& s : ((Block&) *f.fBody).fStatements) {
this->writeStatement(*s);
this->writeLine();
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.h b/src/sksl/SkSLPipelineStageCodeGenerator.h
index 09b40ce..9de7a4a 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.h
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.h
@@ -36,6 +36,8 @@
void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence) override;
+ void writeFunctionCall(const FunctionCall& c) override;
+
void writeIntLiteral(const IntLiteral& i) override;
void writeVariableReference(const VariableReference& ref) override;
diff --git a/src/sksl/sksl_pipeline.inc b/src/sksl/sksl_pipeline.inc
index f0a2221..f1e749f 100644
--- a/src/sksl/sksl_pipeline.inc
+++ b/src/sksl/sksl_pipeline.inc
@@ -16,4 +16,6 @@
layout(builtin=10009) int sk_x;
layout(builtin=10010) int sk_y;
layout(builtin=10004) out half4 sk_OutColor;
+
+ half4 process(fragmentProcessor fp);
)