Add sample(child, matrix) to SkSL.
This allows fragment processors to sample their children with their local coordinate system transformed by a matrix. Change-Id: Ifa848bbd85b939bbc5751fec5cf8f89ee904bf39 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/282590 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
505dc179b0
commit
5843012837
@ -38,7 +38,7 @@ public:
|
||||
|
||||
SampleCoordEffect(std::unique_ptr<GrFragmentProcessor> child)
|
||||
: INHERITED(CLASS_ID, kNone_OptimizationFlags) {
|
||||
child->setSampledWithExplicitCoords(true);
|
||||
child->setSampledWithExplicitCoords();
|
||||
this->registerChildProcessor(std::move(child));
|
||||
}
|
||||
|
||||
|
97
gm/sample_matrix_constant.cpp
Normal file
97
gm/sample_matrix_constant.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm/gm.h"
|
||||
#include "include/effects/SkGradientShader.h"
|
||||
#include "src/gpu/GrBitmapTextureMaker.h"
|
||||
#include "src/gpu/GrClip.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrRenderTargetContextPriv.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/ops/GrFillRectOp.h"
|
||||
#include "tools/Resources.h"
|
||||
|
||||
class SampleMatrixConstantEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 1;
|
||||
|
||||
SampleMatrixConstantEffect(std::unique_ptr<GrFragmentProcessor> child)
|
||||
: INHERITED(CLASS_ID, kNone_OptimizationFlags) {
|
||||
child->setSampleMatrix(SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kVariable));
|
||||
this->registerChildProcessor(std::move(child));
|
||||
}
|
||||
|
||||
const char* name() const override { return "SampleMatrixConstantEffect"; }
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override {
|
||||
SkASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {
|
||||
}
|
||||
|
||||
bool onIsEqual(const GrFragmentProcessor& that) const override {
|
||||
return this == &that;
|
||||
}
|
||||
|
||||
private:
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
typedef GrFragmentProcessor INHERITED;
|
||||
};
|
||||
|
||||
class GLSLSampleMatrixConstantEffect : public GrGLSLFragmentProcessor {
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString sample = this->invokeChildWithMatrix(0, args, "float3x3(0.5)");
|
||||
fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, sample.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
GrGLSLFragmentProcessor* SampleMatrixConstantEffect::onCreateGLSLInstance() const {
|
||||
return new GLSLSampleMatrixConstantEffect();
|
||||
}
|
||||
|
||||
|
||||
DEF_SIMPLE_GPU_GM(sample_matrix_constant, ctx, rtCtx, canvas, 512, 256) {
|
||||
{
|
||||
SkRect bounds = SkRect::MakeIWH(256, 256);
|
||||
SkBitmap bmp;
|
||||
GetResourceAsBitmap("images/mandrill_256.png", &bmp);
|
||||
GrBitmapTextureMaker maker(ctx, bmp, GrImageTexGenPolicy::kDraw);
|
||||
auto view = maker.view(GrMipMapped::kNo);
|
||||
std::unique_ptr<GrFragmentProcessor> imgFP =
|
||||
GrTextureEffect::Make(std::move(view), bmp.alphaType(), SkMatrix());
|
||||
auto fp = std::unique_ptr<GrFragmentProcessor>(
|
||||
new SampleMatrixConstantEffect(std::move(imgFP)));
|
||||
|
||||
GrPaint paint;
|
||||
paint.addCoverageFragmentProcessor(std::move(fp));
|
||||
rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
|
||||
}
|
||||
|
||||
{
|
||||
GrPaint paint;
|
||||
SkRect bounds = SkRect::MakeLTRB(256, 0, 512, 256);
|
||||
static constexpr SkColor colors[] = { 0xff00ff00, 0xffff00ff };
|
||||
static constexpr SkScalar pos[] = { 0.0f, 1.0f };
|
||||
const SkPoint pts[] = {{ 256, 0 }, { 512, 0 }};
|
||||
|
||||
auto shader = SkGradientShader::MakeLinear(pts, colors, pos,
|
||||
SK_ARRAY_COUNT(colors),
|
||||
SkTileMode::kRepeat);
|
||||
SkMatrix matrix;
|
||||
GrColorInfo colorInfo;
|
||||
GrFPArgs args(ctx, &matrix, kHigh_SkFilterQuality, &colorInfo);
|
||||
std::unique_ptr<GrFragmentProcessor> gradientFP = as_SB(shader)->asFragmentProcessor(args);
|
||||
auto fp = std::unique_ptr<GrFragmentProcessor>(
|
||||
new SampleMatrixConstantEffect(std::move(gradientFP)));
|
||||
paint.addCoverageFragmentProcessor(std::move(fp));
|
||||
rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
|
||||
}
|
||||
}
|
||||
|
100
gm/sample_matrix_variable.cpp
Normal file
100
gm/sample_matrix_variable.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm/gm.h"
|
||||
#include "include/effects/SkGradientShader.h"
|
||||
#include "src/gpu/GrBitmapTextureMaker.h"
|
||||
#include "src/gpu/GrClip.h"
|
||||
#include "src/gpu/GrContextPriv.h"
|
||||
#include "src/gpu/GrRenderTargetContextPriv.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/ops/GrFillRectOp.h"
|
||||
#include "tools/Resources.h"
|
||||
|
||||
class SampleMatrixVariableEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 2;
|
||||
|
||||
SampleMatrixVariableEffect(std::unique_ptr<GrFragmentProcessor> child)
|
||||
: INHERITED(CLASS_ID, kNone_OptimizationFlags) {
|
||||
child->setSampleMatrix(SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kVariable));
|
||||
this->registerChildProcessor(std::move(child));
|
||||
}
|
||||
|
||||
const char* name() const override { return "SampleMatrixVariableEffect"; }
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override {
|
||||
SkASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {
|
||||
}
|
||||
|
||||
bool onIsEqual(const GrFragmentProcessor& that) const override {
|
||||
return this == &that;
|
||||
}
|
||||
|
||||
private:
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
typedef GrFragmentProcessor INHERITED;
|
||||
};
|
||||
|
||||
class GLSLSampleMatrixVariableEffect : public GrGLSLFragmentProcessor {
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString sample1 = this->invokeChildWithMatrix(0, args, "float3x3(1)");
|
||||
SkString sample2 = this->invokeChildWithMatrix(0, args, "float3x3(1, -1, 0, 1, 0, 0, "
|
||||
"-0.5, 1, 1)");
|
||||
fragBuilder->codeAppendf("%s = (%s + %s) / 2;\n", args.fOutputColor, sample1.c_str(),
|
||||
sample2.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
GrGLSLFragmentProcessor* SampleMatrixVariableEffect::onCreateGLSLInstance() const {
|
||||
return new GLSLSampleMatrixVariableEffect();
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GPU_GM(sample_matrix_variable, ctx, rtCtx, canvas, 512, 256) {
|
||||
{
|
||||
SkRect bounds = SkRect::MakeIWH(256, 256);
|
||||
SkBitmap bmp;
|
||||
GetResourceAsBitmap("images/mandrill_256.png", &bmp);
|
||||
GrBitmapTextureMaker maker(ctx, bmp, GrImageTexGenPolicy::kDraw);
|
||||
auto view = maker.view(GrMipMapped::kNo);
|
||||
std::unique_ptr<GrFragmentProcessor> imgFP =
|
||||
GrTextureEffect::Make(std::move(view), bmp.alphaType(), SkMatrix());
|
||||
imgFP->setSampleMatrix(SkSL::SampleMatrix::Kind::kVariable);
|
||||
auto fp = std::unique_ptr<GrFragmentProcessor>(
|
||||
new SampleMatrixVariableEffect(std::move(imgFP)));
|
||||
|
||||
GrPaint paint;
|
||||
paint.addCoverageFragmentProcessor(std::move(fp));
|
||||
rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
|
||||
}
|
||||
|
||||
{
|
||||
GrPaint paint;
|
||||
SkRect bounds = SkRect::MakeLTRB(256, 0, 512, 256);
|
||||
static constexpr SkColor colors[] = { 0xff00ff00, 0xffff00ff };
|
||||
static constexpr SkScalar pos[] = { 0.0f, 1.0f };
|
||||
const SkPoint pts[] = {{ 256, 0 }, { 512, 0 }};
|
||||
|
||||
auto shader = SkGradientShader::MakeLinear(pts, colors, pos,
|
||||
SK_ARRAY_COUNT(colors),
|
||||
SkTileMode::kRepeat);
|
||||
SkMatrix matrix;
|
||||
GrColorInfo colorInfo;
|
||||
GrFPArgs args(ctx, &matrix, kHigh_SkFilterQuality, &colorInfo);
|
||||
std::unique_ptr<GrFragmentProcessor> gradientFP = as_SB(shader)->asFragmentProcessor(args);
|
||||
gradientFP->setSampleMatrix(SkSL::SampleMatrix::Kind::kVariable);
|
||||
auto fp = std::unique_ptr<GrFragmentProcessor>(
|
||||
new SampleMatrixVariableEffect(std::move(gradientFP)));
|
||||
paint.addCoverageFragmentProcessor(std::move(fp));
|
||||
rtCtx->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), bounds);
|
||||
}
|
||||
}
|
@ -303,6 +303,8 @@ gm_sources = [
|
||||
"$_gm/runtimecolorfilter.cpp",
|
||||
"$_gm/runtimefunctions.cpp",
|
||||
"$_gm/runtimeshader.cpp",
|
||||
"$_gm/sample_matrix_constant.cpp",
|
||||
"$_gm/sample_matrix_variable.cpp",
|
||||
"$_gm/samplelocations.cpp",
|
||||
"$_gm/samplerstress.cpp",
|
||||
"$_gm/savelayer.cpp",
|
||||
|
@ -315,6 +315,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/effects/generated/GrLumaColorFilterEffect.h",
|
||||
"$_src/gpu/effects/generated/GrMagnifierEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrMagnifierEffect.h",
|
||||
"$_src/gpu/effects/generated/GrMatrixEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrMatrixEffect.h",
|
||||
"$_src/gpu/effects/generated/GrMixerEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrMixerEffect.h",
|
||||
"$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp",
|
||||
@ -471,6 +473,7 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/glsl/GrGLSLProgramDataManager.h",
|
||||
"$_src/gpu/glsl/GrGLSLShaderBuilder.cpp",
|
||||
"$_src/gpu/glsl/GrGLSLShaderBuilder.h",
|
||||
"$_src/gpu/glsl/GrGLSLUniformHandler.cpp",
|
||||
"$_src/gpu/glsl/GrGLSLUniformHandler.h",
|
||||
"$_src/gpu/glsl/GrGLSLVarying.cpp",
|
||||
"$_src/gpu/glsl/GrGLSLVarying.h",
|
||||
|
@ -15,6 +15,7 @@ skia_sksl_sources = [
|
||||
"$_src/sksl/SkSLIRGenerator.cpp",
|
||||
"$_src/sksl/SkSLLexer.cpp",
|
||||
"$_src/sksl/SkSLParser.cpp",
|
||||
"$_src/sksl/SkSLSampleMatrix.cpp",
|
||||
"$_src/sksl/SkSLSectionAndParameterHelper.cpp",
|
||||
"$_src/sksl/SkSLString.cpp",
|
||||
"$_src/sksl/SkSLUtil.cpp",
|
||||
@ -52,6 +53,7 @@ skia_gpu_processor_sources = [
|
||||
"$_src/gpu/effects/GrHSLToRGBFilterEffect.fp",
|
||||
"$_src/gpu/effects/GrLumaColorFilterEffect.fp",
|
||||
"$_src/gpu/effects/GrMagnifierEffect.fp",
|
||||
"$_src/gpu/effects/GrMatrixEffect.fp",
|
||||
"$_src/gpu/effects/GrMixerEffect.fp",
|
||||
"$_src/gpu/effects/GrOverrideInputFragmentProcessor.fp",
|
||||
"$_src/gpu/effects/GrPremulInputFragmentProcessor.fp",
|
||||
|
@ -585,7 +585,8 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
|
||||
fragBuilder->codeAppendf(
|
||||
"\t\t%s.rgb = (%s.a < %s) ? half3(0.0) : saturate(%s.rgb / %s.a);",
|
||||
dColor, dColor, nearZero, dColor, dColor);
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1].fVaryingPoint);
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[1].fVaryingPoint,
|
||||
args.fFp.sampleMatrix());
|
||||
fragBuilder->codeAppendf("\t\tfloat2 %s = %s + %s*(%s.",
|
||||
cCoords, coords2D.c_str(), scaleUni, dColor);
|
||||
|
||||
|
@ -1765,7 +1765,8 @@ void GrGLLightingEffect::emitCode(EmitArgs& args) {
|
||||
GrShaderVar("scale", kHalf_GrSLType),
|
||||
};
|
||||
SkString sobelFuncName;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
args.fFp.sampleMatrix());
|
||||
|
||||
fragBuilder->emitFunction(kHalf_GrSLType,
|
||||
"sobel",
|
||||
|
@ -297,7 +297,8 @@ void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
|
||||
const char* range = uniformHandler->getUniformCStr(fRangeUni);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
args.fFp.sampleMatrix());
|
||||
const char* func;
|
||||
switch (me.type()) {
|
||||
case MorphType::kErode:
|
||||
|
@ -74,6 +74,28 @@ void GrFragmentProcessor::addCoordTransform(GrCoordTransform* transform) {
|
||||
fFlags |= kHasCoordTransforms_Flag;
|
||||
}
|
||||
|
||||
void GrFragmentProcessor::setSampleMatrix(SkSL::SampleMatrix matrix) {
|
||||
if (matrix == fMatrix) {
|
||||
return;
|
||||
}
|
||||
SkASSERT(fMatrix.fKind != SkSL::SampleMatrix::Kind::kVariable);
|
||||
if (fMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) {
|
||||
SkASSERT(matrix.fKind == SkSL::SampleMatrix::Kind::kVariable ||
|
||||
(matrix.fKind == SkSL::SampleMatrix::Kind::kMixed &&
|
||||
matrix.fExpression == fMatrix.fExpression));
|
||||
fMatrix = SkSL::SampleMatrix(SkSL::SampleMatrix::Kind::kMixed, fMatrix.fOwner,
|
||||
fMatrix.fExpression);
|
||||
} else {
|
||||
SkASSERT(fMatrix.fKind == SkSL::SampleMatrix::Kind::kNone);
|
||||
fMatrix = matrix;
|
||||
}
|
||||
if (matrix.fKind == SkSL::SampleMatrix::Kind::kVariable) {
|
||||
for (auto& child : fChildProcessors) {
|
||||
child->setSampleMatrix(matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
bool GrFragmentProcessor::isInstantiated() const {
|
||||
for (int i = 0; i < fTextureSamplerCnt; ++i) {
|
||||
@ -100,7 +122,8 @@ int GrFragmentProcessor::registerChildProcessor(std::unique_ptr<GrFragmentProces
|
||||
|
||||
int index = fChildProcessors.count();
|
||||
fChildProcessors.push_back(std::move(child));
|
||||
|
||||
SkASSERT(fMatrix.fKind == SkSL::SampleMatrix::Kind::kNone ||
|
||||
fMatrix.fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform);
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "src/gpu/GrCoordTransform.h"
|
||||
#include "src/gpu/GrProcessor.h"
|
||||
#include "src/gpu/ops/GrOp.h"
|
||||
#include "src/sksl/SkSLSampleMatrix.h"
|
||||
|
||||
class GrGLSLFragmentProcessor;
|
||||
class GrPaint;
|
||||
@ -145,17 +146,19 @@ public:
|
||||
return SkToBool(fFlags & kSampledWithExplicitCoords);
|
||||
}
|
||||
|
||||
void setSampledWithExplicitCoords(bool value) {
|
||||
if (value) {
|
||||
fFlags |= kSampledWithExplicitCoords;
|
||||
} else {
|
||||
fFlags &= ~kSampledWithExplicitCoords;
|
||||
}
|
||||
void setSampledWithExplicitCoords() {
|
||||
fFlags |= kSampledWithExplicitCoords;
|
||||
for (auto& child : fChildProcessors) {
|
||||
child->setSampledWithExplicitCoords(value);
|
||||
child->setSampledWithExplicitCoords();
|
||||
}
|
||||
}
|
||||
|
||||
SkSL::SampleMatrix sampleMatrix() const {
|
||||
return fMatrix;
|
||||
}
|
||||
|
||||
void setSampleMatrix(SkSL::SampleMatrix matrix);
|
||||
|
||||
/**
|
||||
* A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color
|
||||
* output under the following scenario:
|
||||
@ -466,6 +469,8 @@ private:
|
||||
|
||||
SkSTArray<1, std::unique_ptr<GrFragmentProcessor>, true> fChildProcessors;
|
||||
|
||||
SkSL::SampleMatrix fMatrix;
|
||||
|
||||
typedef GrProcessor INHERITED;
|
||||
};
|
||||
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
&name)
|
||||
.toIndex();
|
||||
transformVar = uniformHandler->getUniformVariable(uni.fHandle);
|
||||
matrix = name;
|
||||
}
|
||||
} else {
|
||||
SkString strVaryingName;
|
||||
@ -106,7 +107,7 @@ public:
|
||||
matrix = matrix_to_sksl(coordTransform.matrix());
|
||||
fragmentVar = {SkString(v.fsIn()), varyingType};
|
||||
}
|
||||
transformHandler->specifyCoordsForCurrCoordTransform(transformVar, fragmentVar);
|
||||
transformHandler->specifyCoordsForCurrCoordTransform(matrix, transformVar, fragmentVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,6 +117,7 @@ public:
|
||||
kGrLumaColorFilterEffect_ClassID,
|
||||
kGrMagnifierEffect_ClassID,
|
||||
kGrMatrixConvolutionEffect_ClassID,
|
||||
kGrMatrixEffect_ClassID,
|
||||
kGrMeshTestProcessor_ClassID,
|
||||
kGrMorphologyEffect_ClassID,
|
||||
kGrMixerEffect_ClassID,
|
||||
|
@ -29,6 +29,14 @@ public:
|
||||
};
|
||||
uint32_t getRTHeightOffset() const;
|
||||
|
||||
int numUniforms() const override {
|
||||
return fUniforms.count();
|
||||
}
|
||||
|
||||
UniformInfo& uniform(int idx) override {
|
||||
return fUniforms.item(idx);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit GrDawnUniformHandler(GrGLSLProgramBuilder* program);
|
||||
|
||||
@ -45,7 +53,6 @@ private:
|
||||
int arrayCount,
|
||||
const char** outName) override;
|
||||
|
||||
|
||||
UniformInfoArray fUniforms;
|
||||
UniformInfoArray fSamplers;
|
||||
UniformInfoArray fTextures;
|
||||
|
@ -26,7 +26,8 @@ void GrBicubicEffect::Impl::emitCode(EmitArgs& args) {
|
||||
const GrBicubicEffect& bicubicEffect = args.fFp.cast<GrBicubicEffect>();
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
bicubicEffect.sampleMatrix());
|
||||
|
||||
/*
|
||||
* Filter weights come from Don Mitchell & Arun Netravali's 'Reconstruction Filters in Computer
|
||||
@ -175,7 +176,7 @@ GrBicubicEffect::GrBicubicEffect(std::unique_ptr<GrFragmentProcessor> fp,
|
||||
, fCoordTransform(matrix)
|
||||
, fDirection(direction)
|
||||
, fClamp(clamp) {
|
||||
fp->setSampledWithExplicitCoords(true);
|
||||
fp->setSampledWithExplicitCoords();
|
||||
this->addCoordTransform(&fCoordTransform);
|
||||
this->registerChildProcessor(std::move(fp));
|
||||
}
|
||||
@ -187,7 +188,7 @@ GrBicubicEffect::GrBicubicEffect(const GrBicubicEffect& that)
|
||||
, fClamp(that.fClamp) {
|
||||
this->addCoordTransform(&fCoordTransform);
|
||||
auto child = that.childProcessor(0).clone();
|
||||
child->setSampledWithExplicitCoords(true);
|
||||
child->setSampledWithExplicitCoords();
|
||||
this->registerChildProcessor(std::move(child));
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,8 @@ void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
|
||||
"Kernel", arrayCount);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
ce.sampleMatrix());
|
||||
|
||||
fragBuilder->codeAppendf("%s = half4(0, 0, 0, 0);", args.fOutputColor);
|
||||
|
||||
|
@ -63,7 +63,8 @@ void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
|
||||
const char* bias = uniformHandler->getUniformCStr(fBiasUni);
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
mce.sampleMatrix());
|
||||
fragBuilder->codeAppend("half4 sum = half4(0, 0, 0, 0);");
|
||||
fragBuilder->codeAppendf("float2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
|
||||
fragBuilder->codeAppend("half4 c;");
|
||||
|
25
src/gpu/effects/GrMatrixEffect.fp
Normal file
25
src/gpu/effects/GrMatrixEffect.fp
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
in uniform float3x3 matrix;
|
||||
in fragmentProcessor child;
|
||||
|
||||
@class {
|
||||
static std::unique_ptr<GrFragmentProcessor> Apply(const SkMatrix& matrix,
|
||||
std::unique_ptr<GrFragmentProcessor> processor) {
|
||||
if (matrix.isIdentity()) {
|
||||
return processor;
|
||||
}
|
||||
SkASSERT(!processor->isSampledWithExplicitCoords());
|
||||
SkASSERT(processor->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone);
|
||||
return Make(matrix, std::move(processor));
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
sk_OutColor = sample(child, sk_InColor, matrix);
|
||||
}
|
@ -89,7 +89,8 @@ public:
|
||||
}
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkASSERT(args.fTransformedCoords.count() == 1);
|
||||
SkString coords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString coords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
fp.sampleMatrix());
|
||||
std::vector<SkString> childNames;
|
||||
// We need to ensure that we call invokeChild on each child FP at least once.
|
||||
// Any child FP that isn't sampled won't trigger a call otherwise, leading to asserts later.
|
||||
@ -204,7 +205,7 @@ const char* GrSkSLFP::name() const {
|
||||
}
|
||||
|
||||
void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
|
||||
child->setSampledWithExplicitCoords(true);
|
||||
child->setSampledWithExplicitCoords();
|
||||
this->registerChildProcessor(std::move(child));
|
||||
}
|
||||
|
||||
|
@ -227,18 +227,26 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
|
||||
public:
|
||||
void emitCode(EmitArgs& args) override {
|
||||
auto& te = args.fFp.cast<GrTextureEffect>();
|
||||
const char* coords;
|
||||
if (args.fFp.isSampledWithExplicitCoords()) {
|
||||
coords = "_coords";
|
||||
} else {
|
||||
coords = args.fTransformedCoords[0].fVaryingPoint.c_str();
|
||||
}
|
||||
auto* fb = args.fFragBuilder;
|
||||
if (te.fShaderModes[0] == ShaderMode::kNone &&
|
||||
te.fShaderModes[1] == ShaderMode::kNone) {
|
||||
SkString coords;
|
||||
if (args.fFp.isSampledWithExplicitCoords()) {
|
||||
coords = "_coords";
|
||||
} else {
|
||||
coords = args.fTransformedCoords[0].fVaryingPoint.c_str();
|
||||
}
|
||||
switch (te.sampleMatrix().fKind) {
|
||||
case SkSL::SampleMatrix::Kind::kMixed:
|
||||
case SkSL::SampleMatrix::Kind::kVariable:
|
||||
coords = SkStringPrintf("(_matrix * float3(%s, 1)).xy", coords.c_str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fb->codeAppendf("%s = ", args.fOutputColor);
|
||||
fb->appendTextureLookupAndBlend(args.fInputColor, SkBlendMode::kModulate,
|
||||
args.fTexSamplers[0], coords);
|
||||
args.fTexSamplers[0], coords.c_str());
|
||||
fb->codeAppendf(";");
|
||||
} else {
|
||||
// Here is the basic flow of the various ShaderModes are implemented in a series of
|
||||
@ -262,7 +270,8 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
|
||||
// Convert possible projective texture coordinates into non-homogeneous half2.
|
||||
fb->codeAppendf(
|
||||
"float2 inCoord = %s;",
|
||||
fb->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint).c_str());
|
||||
fb->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
te.sampleMatrix()).c_str());
|
||||
|
||||
const auto& m = te.fShaderModes;
|
||||
GrTextureType textureType = te.fSampler.proxy()->backendFormat().textureType();
|
||||
|
@ -41,8 +41,8 @@ public:
|
||||
kHalf_GrSLType, "innerThreshold");
|
||||
outerThresholdVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
|
||||
kHalf_GrSLType, "outerThreshold");
|
||||
SkString sk_TransformedCoords2D_0 =
|
||||
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
|
||||
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
|
||||
fragBuilder->codeAppendf(
|
||||
"half4 color = %s;\nhalf4 mask_color = sample(%s, %s).%s;\nif (mask_color.w < 0.5) "
|
||||
"{\n if (color.w > %s) {\n half scale = %s / color.w;\n color.xyz "
|
||||
|
@ -72,14 +72,16 @@ GrComposeLerpEffect::GrComposeLerpEffect(const GrComposeLerpEffect& src)
|
||||
, weight(src.weight) {
|
||||
if (child1_index >= 0) {
|
||||
auto clone = src.childProcessor(child1_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(child1_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(child1_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
if (child2_index >= 0) {
|
||||
auto clone = src.childProcessor(child2_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(child2_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(child2_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
|
@ -49,8 +49,9 @@ GrDeviceSpaceEffect::GrDeviceSpaceEffect(const GrDeviceSpaceEffect& src)
|
||||
: INHERITED(kGrDeviceSpaceEffect_ClassID, src.optimizationFlags()), fp_index(src.fp_index) {
|
||||
{
|
||||
auto clone = src.childProcessor(fp_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(fp_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(fp_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ private:
|
||||
: INHERITED(kGrDeviceSpaceEffect_ClassID, kNone_OptimizationFlags) {
|
||||
SkASSERT(fp);
|
||||
fp_index = this->numChildProcessors();
|
||||
fp->setSampledWithExplicitCoords(true);
|
||||
fp->setSampledWithExplicitCoords();
|
||||
this->registerChildProcessor(std::move(fp));
|
||||
}
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
|
@ -47,8 +47,8 @@ public:
|
||||
&_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "yInvInset");
|
||||
offsetVar = args.fUniformHandler->addUniform(
|
||||
&_outer, kFragment_GrShaderFlag, kHalf2_GrSLType, "offset");
|
||||
SkString sk_TransformedCoords2D_0 =
|
||||
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
|
||||
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 coord = %s;\nfloat2 zoom_coord = float2(%s) + coord * float2(%s, "
|
||||
"%s);\nfloat2 delta = (coord - %s.xy) * %s.zw;\ndelta = min(delta, "
|
||||
|
69
src/gpu/effects/generated/GrMatrixEffect.cpp
Normal file
69
src/gpu/effects/generated/GrMatrixEffect.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* 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 GrMatrixEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#include "GrMatrixEffect.h"
|
||||
|
||||
#include "src/gpu/GrTexture.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
|
||||
#include "src/sksl/SkSLCPP.h"
|
||||
#include "src/sksl/SkSLUtil.h"
|
||||
class GrGLSLMatrixEffect : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLMatrixEffect() {}
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrMatrixEffect& _outer = args.fFp.cast<GrMatrixEffect>();
|
||||
(void)_outer;
|
||||
auto matrix = _outer.matrix;
|
||||
(void)matrix;
|
||||
matrixVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
|
||||
kFloat3x3_GrSLType, "matrix");
|
||||
SkString _input716 = SkStringPrintf("%s", args.fInputColor);
|
||||
SkString _sample716;
|
||||
_sample716 = this->invokeChild(_outer.child_index, _input716.c_str(), args);
|
||||
fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, _sample716.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {
|
||||
const GrMatrixEffect& _outer = _proc.cast<GrMatrixEffect>();
|
||||
{ pdman.setSkMatrix(matrixVar, (_outer.matrix)); }
|
||||
}
|
||||
UniformHandle matrixVar;
|
||||
};
|
||||
GrGLSLFragmentProcessor* GrMatrixEffect::onCreateGLSLInstance() const {
|
||||
return new GrGLSLMatrixEffect();
|
||||
}
|
||||
void GrMatrixEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {}
|
||||
bool GrMatrixEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrMatrixEffect& that = other.cast<GrMatrixEffect>();
|
||||
(void)that;
|
||||
if (matrix != that.matrix) return false;
|
||||
return true;
|
||||
}
|
||||
GrMatrixEffect::GrMatrixEffect(const GrMatrixEffect& src)
|
||||
: INHERITED(kGrMatrixEffect_ClassID, src.optimizationFlags())
|
||||
, matrix(src.matrix)
|
||||
, child_index(src.child_index) {
|
||||
{
|
||||
auto clone = src.childProcessor(child_index).clone();
|
||||
if (src.childProcessor(child_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrMatrixEffect::clone() const {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(*this));
|
||||
}
|
52
src/gpu/effects/generated/GrMatrixEffect.h
Normal file
52
src/gpu/effects/generated/GrMatrixEffect.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* 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 GrMatrixEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#ifndef GrMatrixEffect_DEFINED
|
||||
#define GrMatrixEffect_DEFINED
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/core/SkM44.h"
|
||||
|
||||
#include "src/gpu/GrCoordTransform.h"
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
class GrMatrixEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static std::unique_ptr<GrFragmentProcessor> Apply(
|
||||
const SkMatrix& matrix, std::unique_ptr<GrFragmentProcessor> processor) {
|
||||
if (matrix.isIdentity()) {
|
||||
return processor;
|
||||
}
|
||||
SkASSERT(!processor->isSampledWithExplicitCoords());
|
||||
SkASSERT(processor->sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kNone);
|
||||
return Make(matrix, std::move(processor));
|
||||
}
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(SkMatrix matrix,
|
||||
std::unique_ptr<GrFragmentProcessor> child) {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrMatrixEffect(matrix, std::move(child)));
|
||||
}
|
||||
GrMatrixEffect(const GrMatrixEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "MatrixEffect"; }
|
||||
SkMatrix matrix;
|
||||
int child_index = -1;
|
||||
|
||||
private:
|
||||
GrMatrixEffect(SkMatrix matrix, std::unique_ptr<GrFragmentProcessor> child)
|
||||
: INHERITED(kGrMatrixEffect_ClassID, kNone_OptimizationFlags), matrix(matrix) {
|
||||
SkASSERT(child);
|
||||
child_index = this->numChildProcessors();
|
||||
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
|
||||
typedef GrFragmentProcessor INHERITED;
|
||||
};
|
||||
#endif
|
@ -70,14 +70,16 @@ GrMixerEffect::GrMixerEffect(const GrMixerEffect& src)
|
||||
, weight(src.weight) {
|
||||
{
|
||||
auto clone = src.childProcessor(fp0_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(fp0_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(fp0_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
if (fp1_index >= 0) {
|
||||
auto clone = src.childProcessor(fp1_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(fp1_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(fp1_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
|
@ -93,8 +93,9 @@ GrOverrideInputFragmentProcessor::GrOverrideInputFragmentProcessor(
|
||||
, literalColor(src.literalColor) {
|
||||
{
|
||||
auto clone = src.childProcessor(fp_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(fp_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(fp_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,15 @@ public:
|
||||
const char* getUniformCStr(UniformHandle u) const override {
|
||||
return this->getUniformVariable(u).c_str();
|
||||
}
|
||||
|
||||
int numUniforms() const override {
|
||||
return fUniforms.count();
|
||||
}
|
||||
|
||||
UniformInfo& uniform(int idx) override {
|
||||
return fUniforms.item(idx);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit GrGLUniformHandler(GrGLSLProgramBuilder* program)
|
||||
: INHERITED(program)
|
||||
@ -64,9 +73,9 @@ private:
|
||||
typedef GrGLProgramDataManager::GLUniformInfo GLUniformInfo;
|
||||
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
|
||||
|
||||
UniformInfoArray fUniforms;
|
||||
UniformInfoArray fSamplers;
|
||||
SkTArray<GrSwizzle> fSamplerSwizzles;
|
||||
UniformInfoArray fUniforms;
|
||||
UniformInfoArray fSamplers;
|
||||
SkTArray<GrSwizzle> fSamplerSwizzles;
|
||||
|
||||
friend class GrGLProgramBuilder;
|
||||
|
||||
|
@ -36,6 +36,21 @@ SkString GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputC
|
||||
|
||||
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
|
||||
|
||||
// If the fragment processor is invoked with overridden coordinates, it must *always* be invoked
|
||||
// with overridden coords.
|
||||
SkASSERT(childProc.isSampledWithExplicitCoords() == !skslCoords.empty());
|
||||
|
||||
if (skslCoords.length() == 0) {
|
||||
switch (childProc.sampleMatrix().fKind) {
|
||||
case SkSL::SampleMatrix::Kind::kMixed:
|
||||
case SkSL::SampleMatrix::Kind::kVariable:
|
||||
skslCoords = "_matrix";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the child's helper function if this is the first time we've seen a call
|
||||
if (fFunctionNames[childIndex].size() == 0) {
|
||||
fragBuilder->onBeforeChildProcEmitCode(); // call first so mangleString is updated
|
||||
@ -57,10 +72,6 @@ SkString GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputC
|
||||
fragBuilder->onAfterChildProcEmitCode();
|
||||
}
|
||||
|
||||
// If the fragment processor is invoked with overridden coordinates, it must *always* be invoked
|
||||
// with overridden coords.
|
||||
SkASSERT(childProc.isSampledWithExplicitCoords() == !skslCoords.empty());
|
||||
|
||||
// Produce a string containing the call to the helper function
|
||||
SkString result = SkStringPrintf("%s(%s", fFunctionNames[childIndex].c_str(),
|
||||
inputColor ? inputColor : "half4(1)");
|
||||
@ -71,6 +82,43 @@ SkString GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputC
|
||||
return result;
|
||||
}
|
||||
|
||||
SkString GrGLSLFragmentProcessor::invokeChildWithMatrix(int childIndex, const char* inputColor,
|
||||
EmitArgs& args,
|
||||
SkSL::String skslMatrix) {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
while (childIndex >= (int) fFunctionNames.size()) {
|
||||
fFunctionNames.emplace_back();
|
||||
}
|
||||
|
||||
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
|
||||
|
||||
// Emit the child's helper function if this is the first time we've seen a call
|
||||
if (fFunctionNames[childIndex].size() == 0) {
|
||||
fragBuilder->onBeforeChildProcEmitCode(); // call first so mangleString is updated
|
||||
|
||||
TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
|
||||
TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
|
||||
|
||||
EmitArgs childArgs(fragBuilder,
|
||||
args.fUniformHandler,
|
||||
args.fShaderCaps,
|
||||
childProc,
|
||||
"_output",
|
||||
"_input",
|
||||
coordVars,
|
||||
textureSamplers);
|
||||
fFunctionNames[childIndex] =
|
||||
fragBuilder->writeProcessorFunction(this->childProcessor(childIndex), childArgs);
|
||||
|
||||
fragBuilder->onAfterChildProcEmitCode();
|
||||
}
|
||||
|
||||
// Produce a string containing the call to the helper function
|
||||
return SkStringPrintf("%s(%s, %s)", fFunctionNames[childIndex].c_str(),
|
||||
inputColor ? inputColor : "half4(1)",
|
||||
skslMatrix.c_str());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrGLSLFragmentProcessor::Iter::Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt) {
|
||||
|
@ -142,6 +142,11 @@ public:
|
||||
return this->invokeChild(childIndex, nullptr, parentArgs, skslCoords);
|
||||
}
|
||||
|
||||
inline SkString invokeChildWithMatrix(int childIndex, EmitArgs& parentArgs,
|
||||
SkSL::String skslMatrix) {
|
||||
return this->invokeChildWithMatrix(childIndex, nullptr, parentArgs, skslMatrix);
|
||||
}
|
||||
|
||||
/** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will
|
||||
* automatically extract the coords and samplers of that child and pass them on to the child's
|
||||
* emitCode(). Also, any uniforms or functions emitted by the child will have their names
|
||||
@ -152,6 +157,12 @@ public:
|
||||
SkString invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs,
|
||||
SkSL::String skslCoords = "");
|
||||
|
||||
/**
|
||||
* As invokeChild, but transforms the coordinates according to the provided matrix. The matrix
|
||||
* must be a snippet of SkSL code which evaluates to a float3x3.
|
||||
*/
|
||||
SkString invokeChildWithMatrix(int childIndex, const char* inputColor, EmitArgs& parentArgs,
|
||||
SkSL::String skslMatrix);
|
||||
/**
|
||||
* Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
|
||||
* GLSLFPS. If initialized with an array color followed by coverage processors installed in a
|
||||
|
@ -71,20 +71,30 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
|
||||
fSubstageIndices.push_back(0);
|
||||
}
|
||||
|
||||
SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
|
||||
SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords,
|
||||
const SkSL::SampleMatrix& matrix) {
|
||||
SkString result;
|
||||
if (!coords.getName().size()) {
|
||||
return SkString("_coords");
|
||||
}
|
||||
if (kFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
|
||||
result = "_coords";
|
||||
} else if (kFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
|
||||
SkASSERT(kFloat2_GrSLType == coords.getType() || kHalf2_GrSLType == coords.getType());
|
||||
return coords.getName();
|
||||
result = coords.getName();
|
||||
} else {
|
||||
SkString coords2D;
|
||||
coords2D.printf("%s_ensure2D", coords.c_str());
|
||||
this->codeAppendf("\tfloat2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(),
|
||||
coords.c_str());
|
||||
result = coords2D;
|
||||
}
|
||||
|
||||
SkString coords2D;
|
||||
coords2D.printf("%s_ensure2D", coords.c_str());
|
||||
this->codeAppendf("\tfloat2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(),
|
||||
coords.c_str());
|
||||
return coords2D;
|
||||
switch (matrix.fKind) {
|
||||
case SkSL::SampleMatrix::Kind::kMixed:
|
||||
case SkSL::SampleMatrix::Kind::kVariable:
|
||||
result = SkStringPrintf("(_matrix * float3(%s, 1)).xy", result.c_str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* GrGLSLFragmentShaderBuilder::sampleOffsets() {
|
||||
@ -163,6 +173,8 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor
|
||||
GrGLSLFragmentProcessor::EmitArgs& args) {
|
||||
this->onBeforeChildProcEmitCode();
|
||||
this->nextStage();
|
||||
bool hasVariableMatrix = args.fFp.sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kVariable ||
|
||||
args.fFp.sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kMixed;
|
||||
if (args.fFp.isSampledWithExplicitCoords() && args.fTransformedCoords.count() > 0) {
|
||||
// we currently only support overriding a single coordinate pair
|
||||
SkASSERT(args.fTransformedCoords.count() == 1);
|
||||
@ -179,16 +191,27 @@ SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor
|
||||
SkASSERT(transform.getType() == kVoid_GrSLType);
|
||||
break;
|
||||
}
|
||||
if (args.fFp.sampleMatrix().fKind != SkSL::SampleMatrix::Kind::kNone) {
|
||||
SkASSERT(!hasVariableMatrix);
|
||||
this->codeAppend("{\n");
|
||||
args.fUniformHandler->writeUniformMappings(args.fFp.sampleMatrix().fOwner, this);
|
||||
this->codeAppendf("_coords = (%s * float3(_coords, 1)).xy;\n",
|
||||
args.fFp.sampleMatrix().fExpression.c_str());
|
||||
this->codeAppend("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
this->codeAppendf("half4 %s;\n", args.fOutputColor);
|
||||
fp->emitCode(args);
|
||||
this->codeAppendf("return %s;\n", args.fOutputColor);
|
||||
GrShaderVar params[] = { GrShaderVar(args.fInputColor, kHalf4_GrSLType),
|
||||
GrShaderVar("_coords", kFloat2_GrSLType) };
|
||||
hasVariableMatrix ? GrShaderVar("_matrix", kFloat3x3_GrSLType)
|
||||
: GrShaderVar("_coords", kFloat2_GrSLType) };
|
||||
SkString result;
|
||||
this->emitFunction(kHalf4_GrSLType,
|
||||
args.fFp.name(),
|
||||
args.fFp.isSampledWithExplicitCoords() ? 2 : 1,
|
||||
args.fFp.isSampledWithExplicitCoords() || hasVariableMatrix ? 2
|
||||
: 1,
|
||||
params,
|
||||
this->code().c_str(),
|
||||
&result);
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
* the coordinates are 3-dimensional, it a perspective divide into is emitted into the
|
||||
* fragment shader (xy / z) to convert them to 2D.
|
||||
*/
|
||||
virtual SkString ensureCoords2D(const GrShaderVar&) = 0;
|
||||
virtual SkString ensureCoords2D(const GrShaderVar&, const SkSL::SampleMatrix& matrix) = 0;
|
||||
|
||||
// TODO: remove this method.
|
||||
void declAppendf(const char* fmt, ...);
|
||||
@ -153,7 +153,8 @@ public:
|
||||
GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program);
|
||||
|
||||
// Shared GrGLSLFragmentBuilder interface.
|
||||
virtual SkString ensureCoords2D(const GrShaderVar&) override;
|
||||
virtual SkString ensureCoords2D(const GrShaderVar&,
|
||||
const SkSL::SampleMatrix& matrix) override;
|
||||
|
||||
// GrGLSLFPFragmentBuilder interface.
|
||||
const char* sampleOffsets() override;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
|
||||
|
||||
#include "src/gpu/GrCoordTransform.h"
|
||||
#include "src/gpu/GrPipeline.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
|
||||
#include "src/gpu/glsl/GrGLSLVarying.h"
|
||||
@ -84,7 +85,7 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
for (int i = 0; *handler; ++*handler, ++i) {
|
||||
auto [coordTransform, fp] = handler->get();
|
||||
// Add uniform for coord transform matrix.
|
||||
const char* matrixName;
|
||||
SkString matrix;
|
||||
if (!fp.isSampledWithExplicitCoords() || !coordTransform.isNoOp()) {
|
||||
SkString strUniName;
|
||||
strUniName.printf("CoordTransformMatrix_%d", i);
|
||||
@ -96,9 +97,11 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
} else {
|
||||
uni.fType = kFloat3x3_GrSLType;
|
||||
}
|
||||
const char* matrixName;
|
||||
uni.fHandle =
|
||||
uniformHandler->addUniform(&fp, flag, uni.fType, strUniName.c_str(),
|
||||
&matrixName);
|
||||
matrix = matrixName;
|
||||
transformVar = uniformHandler->getUniformVariable(uni.fHandle);
|
||||
} else {
|
||||
// Install a coord transform that will be skipped.
|
||||
@ -122,14 +125,45 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
|
||||
|
||||
SkASSERT(fInstalledTransforms.back().fType == kFloat3x3_GrSLType);
|
||||
if (v.type() == kFloat2_GrSLType) {
|
||||
vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), matrixName,
|
||||
vb->codeAppendf("%s = (%s * %s).xy;", v.vsOut(), matrix.c_str(),
|
||||
localCoordsStr.c_str());
|
||||
} else {
|
||||
vb->codeAppendf("%s = %s * %s;", v.vsOut(), matrixName, localCoordsStr.c_str());
|
||||
vb->codeAppendf("%s = %s * %s;", v.vsOut(), matrix.c_str(), localCoordsStr.c_str());
|
||||
}
|
||||
fsVar = GrShaderVar(SkString(v.fsIn()), v.type(), GrShaderVar::TypeModifier::In);
|
||||
fTransformInfos.push_back({ v.vsOut(), v.type(), matrix.c_str(), localCoordsStr, &fp });
|
||||
} else {
|
||||
SkASSERT(fp.sampleMatrix().fKind != SkSL::SampleMatrix::Kind::kVariable);
|
||||
if (fp.sampleMatrix().fKind == SkSL::SampleMatrix::Kind::kConstantOrUniform) {
|
||||
matrix += " * " + fp.sampleMatrix().fExpression;
|
||||
}
|
||||
}
|
||||
handler->specifyCoordsForCurrCoordTransform(matrix, transformVar, fsVar);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLSLGeometryProcessor::emitTransformCode(GrGLSLVertexBuilder* vb,
|
||||
GrGLSLUniformHandler* uniformHandler) {
|
||||
for (const auto& tr : fTransformInfos) {
|
||||
switch (tr.fFP->sampleMatrix().fKind) {
|
||||
case SkSL::SampleMatrix::Kind::kConstantOrUniform:
|
||||
vb->codeAppend("{\n");
|
||||
uniformHandler->writeUniformMappings(tr.fFP->sampleMatrix().fOwner, vb);
|
||||
if (tr.fType == kFloat2_GrSLType) {
|
||||
vb->codeAppendf("%s = (%s * %s * %s).xy", tr.fName,
|
||||
tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix,
|
||||
tr.fLocalCoords.c_str());
|
||||
} else {
|
||||
SkASSERT(tr.fType == kFloat3_GrSLType);
|
||||
vb->codeAppendf("%s = %s * %s * %s", tr.fName,
|
||||
tr.fFP->sampleMatrix().fExpression.c_str(), tr.fMatrix,
|
||||
tr.fName);
|
||||
}
|
||||
vb->codeAppend(";\n");
|
||||
vb->codeAppend("}\n");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
handler->specifyCoordsForCurrCoordTransform(transformVar, fsVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,10 @@ protected:
|
||||
handler);
|
||||
}
|
||||
|
||||
// TODO: doc
|
||||
void emitTransformCode(GrGLSLVertexBuilder* vb,
|
||||
GrGLSLUniformHandler* uniformHandler) override;
|
||||
|
||||
struct GrGPArgs {
|
||||
// Used to specify the output variable used by the GP to store its device position. It can
|
||||
// either be a float2 or a float3 (in order to handle perspective). The subclass sets this
|
||||
@ -90,6 +94,15 @@ private:
|
||||
|
||||
SkTArray<TransformUniform, true> fInstalledTransforms;
|
||||
|
||||
struct TransformInfo {
|
||||
const char* fName;
|
||||
GrSLType fType;
|
||||
const char* fMatrix;
|
||||
SkString fLocalCoords;
|
||||
const GrFragmentProcessor* fFP;
|
||||
};
|
||||
SkTArray<TransformInfo> fTransformInfos;
|
||||
|
||||
typedef GrGLSLPrimitiveProcessor INHERITED;
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,8 @@ public:
|
||||
FPCoordTransformHandler& operator++();
|
||||
|
||||
// 'args' are constructor params to GrShaderVar.
|
||||
void specifyCoordsForCurrCoordTransform(GrShaderVar transformVar, GrShaderVar varyingVar) {
|
||||
void specifyCoordsForCurrCoordTransform(/* FIXME name and doc this properly */const SkString& name, GrShaderVar transformVar,
|
||||
GrShaderVar varyingVar) {
|
||||
SkASSERT(!fAddedCoord);
|
||||
fTransformedCoordVars->push_back({transformVar, varyingVar});
|
||||
SkDEBUGCODE(fAddedCoord = true;)
|
||||
@ -123,6 +124,12 @@ public:
|
||||
*/
|
||||
virtual void emitCode(EmitArgs&) = 0;
|
||||
|
||||
/**
|
||||
* Called after all effect emitCode() functions, to give the processor a chance to write out
|
||||
* additional transformation code now that all uniforms have been emitted.
|
||||
*/
|
||||
virtual void emitTransformCode(GrGLSLVertexBuilder* vb,
|
||||
GrGLSLUniformHandler* uniformHandler) {}
|
||||
/**
|
||||
* A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that
|
||||
* produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and
|
||||
|
@ -57,6 +57,7 @@ bool GrGLSLProgramBuilder::emitAndInstallProcs() {
|
||||
this->emitAndInstallPrimProc(&inputColor, &inputCoverage);
|
||||
this->emitAndInstallFragProcs(&inputColor, &inputCoverage);
|
||||
this->emitAndInstallXferProc(inputColor, inputCoverage);
|
||||
fGeometryProcessor->emitTransformCode(&fVS, this->uniformHandler());
|
||||
|
||||
return this->checkSamplerCounts();
|
||||
}
|
||||
|
23
src/gpu/glsl/GrGLSLUniformHandler.cpp
Normal file
23
src/gpu/glsl/GrGLSLUniformHandler.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
|
||||
|
||||
#include "src/gpu/glsl/GrGLSL.h"
|
||||
#include "src/gpu/glsl/GrGLSLShaderBuilder.h"
|
||||
|
||||
void GrGLSLUniformHandler::writeUniformMappings(GrFragmentProcessor* owner,
|
||||
GrGLSLShaderBuilder* b) {
|
||||
for (int i = this->numUniforms() - 1; i >= 0; i--) {
|
||||
UniformInfo& u = this->uniform(i);
|
||||
if (u.fOwner == owner) {
|
||||
u.fVisibility |= kVertex_GrShaderFlag;
|
||||
b->codeAppendf("%s %s = %s;\n", GrGLSLTypeString(u.fVariable.getType()),
|
||||
u.fRawName.c_str(), u.fVariable.getName().c_str());
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
#define GR_NO_MANGLE_PREFIX "sk_"
|
||||
|
||||
class GrGLSLProgramBuilder;
|
||||
class GrGLSLShaderBuilder;
|
||||
class GrSamplerState;
|
||||
class GrSurfaceProxy;
|
||||
|
||||
@ -78,7 +79,21 @@ public:
|
||||
*/
|
||||
virtual const char* getUniformCStr(UniformHandle u) const = 0;
|
||||
|
||||
virtual int numUniforms() const = 0;
|
||||
|
||||
virtual UniformInfo& uniform(int idx) = 0;
|
||||
|
||||
void writeUniformMappings(GrFragmentProcessor* owner, GrGLSLShaderBuilder* b);
|
||||
|
||||
protected:
|
||||
struct UniformMapping {
|
||||
const GrFragmentProcessor* fOwner;
|
||||
int fInfoIndex;
|
||||
SkString fRawName;
|
||||
const char* fFinalName;
|
||||
GrSLType fType;
|
||||
};
|
||||
|
||||
explicit GrGLSLUniformHandler(GrGLSLProgramBuilder* program) : fProgramBuilder(program) {}
|
||||
|
||||
// This is not owned by the class
|
||||
|
@ -103,14 +103,16 @@ GrClampedGradientEffect::GrClampedGradientEffect(const GrClampedGradientEffect&
|
||||
, colorsAreOpaque(src.colorsAreOpaque) {
|
||||
{
|
||||
auto clone = src.childProcessor(colorizer_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(colorizer_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(colorizer_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
{
|
||||
auto clone = src.childProcessor(gradLayout_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(gradLayout_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(gradLayout_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
(void)_outer;
|
||||
auto gradientMatrix = _outer.gradientMatrix;
|
||||
(void)gradientMatrix;
|
||||
SkString sk_TransformedCoords2D_0 =
|
||||
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
|
||||
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
|
||||
fragBuilder->codeAppendf(
|
||||
"half t = half(%s.x) + 9.9999997473787516e-06;\n%s = half4(t, 1.0, 0.0, 0.0);\n",
|
||||
sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
(void)_outer;
|
||||
auto gradientMatrix = _outer.gradientMatrix;
|
||||
(void)gradientMatrix;
|
||||
SkString sk_TransformedCoords2D_0 =
|
||||
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
|
||||
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
|
||||
fragBuilder->codeAppendf("half t = half(length(%s));\n%s = half4(t, 1.0, 0.0, 0.0);\n",
|
||||
sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ public:
|
||||
"bias");
|
||||
scaleVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType,
|
||||
"scale");
|
||||
SkString sk_TransformedCoords2D_0 =
|
||||
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
|
||||
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
|
||||
fragBuilder->codeAppendf(
|
||||
"half angle;\nif (sk_Caps.atan2ImplementedAsAtanYOverX) {\n angle = half(2.0 * "
|
||||
"atan(-%s.y, length(%s) - %s.x));\n} else {\n angle = half(atan(-%s.y, "
|
||||
|
@ -79,14 +79,16 @@ GrTiledGradientEffect::GrTiledGradientEffect(const GrTiledGradientEffect& src)
|
||||
, colorsAreOpaque(src.colorsAreOpaque) {
|
||||
{
|
||||
auto clone = src.childProcessor(colorizer_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(colorizer_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(colorizer_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
{
|
||||
auto clone = src.childProcessor(gradLayout_index).clone();
|
||||
clone->setSampledWithExplicitCoords(
|
||||
src.childProcessor(gradLayout_index).isSampledWithExplicitCoords());
|
||||
if (src.childProcessor(gradLayout_index).isSampledWithExplicitCoords()) {
|
||||
clone->setSampledWithExplicitCoords();
|
||||
}
|
||||
this->registerChildProcessor(std::move(clone));
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ public:
|
||||
(void)focalParams;
|
||||
focalParamsVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
|
||||
kHalf2_GrSLType, "focalParams");
|
||||
SkString sk_TransformedCoords2D_0 =
|
||||
fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(
|
||||
args.fTransformedCoords[0].fVaryingPoint, _outer.sampleMatrix());
|
||||
fragBuilder->codeAppendf(
|
||||
"float2 p = %s;\nfloat t = -1.0;\nhalf v = 1.0;\n@switch (%d) {\n case 1:\n "
|
||||
" {\n half r0_2 = %s.y;\n t = float(r0_2) - p.y * p.y;\n "
|
||||
|
@ -41,6 +41,14 @@ public:
|
||||
return this->getUniformVariable(u).c_str();
|
||||
}
|
||||
|
||||
int numUniforms() const override {
|
||||
return fUniforms.count();
|
||||
}
|
||||
|
||||
UniformInfo& uniform(int idx) override {
|
||||
return fUniforms.item(idx);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit GrMtlUniformHandler(GrGLSLProgramBuilder* program)
|
||||
: INHERITED(program)
|
||||
|
@ -56,6 +56,14 @@ public:
|
||||
*/
|
||||
uint32_t getRTHeightOffset() const;
|
||||
|
||||
int numUniforms() const override {
|
||||
return fUniforms.count();
|
||||
}
|
||||
|
||||
UniformInfo& uniform(int idx) override {
|
||||
return fUniforms.item(idx);
|
||||
}
|
||||
|
||||
private:
|
||||
explicit GrVkUniformHandler(GrGLSLProgramBuilder* program)
|
||||
: INHERITED(program)
|
||||
|
@ -836,7 +836,8 @@ void GrGLPerlinNoise::emitCode(EmitArgs& args) {
|
||||
|
||||
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
pne.sampleMatrix());
|
||||
|
||||
fBaseFrequencyUni = uniformHandler->addUniform(&pne, kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"baseFrequency");
|
||||
@ -1247,7 +1248,8 @@ void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
|
||||
const GrImprovedPerlinNoiseEffect& pne = args.fFp.cast<GrImprovedPerlinNoiseEffect>();
|
||||
GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
|
||||
SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint,
|
||||
pne.sampleMatrix());
|
||||
|
||||
fBaseFrequencyUni = uniformHandler->addUniform(&pne, kFragment_GrShaderFlag, kHalf2_GrSLType,
|
||||
"baseFrequency");
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "src/sksl/SkSLCPPUniformCTypes.h"
|
||||
#include "src/sksl/SkSLCompiler.h"
|
||||
#include "src/sksl/SkSLHCodeGenerator.h"
|
||||
#include "src/sksl/SkSLSampleMatrix.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -126,7 +127,7 @@ void CPPCodeGenerator::writeIndexExpression(const IndexExpression& i) {
|
||||
if (fWrittenTransformedCoords.find(index) == fWrittenTransformedCoords.end()) {
|
||||
addExtraEmitCodeLine("SkString " + name +
|
||||
" = fragBuilder->ensureCoords2D(args.fTransformedCoords[" +
|
||||
to_string(index) + "].fVaryingPoint);");
|
||||
to_string(index) + "].fVaryingPoint, _outer.sampleMatrix());");
|
||||
fWrittenTransformedCoords.insert(index);
|
||||
}
|
||||
return;
|
||||
@ -441,15 +442,20 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
}
|
||||
|
||||
bool hasCoords = c.fArguments.back()->fType.name() == "float2";
|
||||
|
||||
SampleMatrix matrix = fSectionAndParameterHelper.getMatrix(child);
|
||||
// Write the output handling after the possible input handling
|
||||
String childName = "_sample" + to_string(c.fOffset);
|
||||
addExtraEmitCodeLine("SkString " + childName + ";");
|
||||
String coordsName;
|
||||
String matrixName;
|
||||
if (hasCoords) {
|
||||
coordsName = "_coords" + to_string(c.fOffset);
|
||||
addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments.back(), coordsName));
|
||||
}
|
||||
if (matrix.fKind == SampleMatrix::Kind::kVariable) {
|
||||
matrixName = "_matrix" + to_string(c.fOffset);
|
||||
addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments.back(), matrixName));
|
||||
}
|
||||
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
|
||||
addExtraEmitCodeLine("if (_outer." + String(child.fName) + "_index >= 0) {\n ");
|
||||
}
|
||||
@ -457,8 +463,19 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
addExtraEmitCodeLine(childName + " = this->invokeChild(_outer." + String(child.fName) +
|
||||
"_index" + inputArg + ", args, " + coordsName + ".c_str());");
|
||||
} else {
|
||||
addExtraEmitCodeLine(childName + " = this->invokeChild(_outer." + String(child.fName) +
|
||||
"_index" + inputArg + ", args);");
|
||||
switch (matrix.fKind) {
|
||||
case SampleMatrix::Kind::kMixed:
|
||||
case SampleMatrix::Kind::kVariable:
|
||||
addExtraEmitCodeLine(childName + " = this->invokeChildWithMatrix(_outer." +
|
||||
String(child.fName) + "_index" + inputArg + ", args, " +
|
||||
matrixName + ".c_str());");
|
||||
break;
|
||||
case SampleMatrix::Kind::kConstantOrUniform:
|
||||
case SampleMatrix::Kind::kNone:
|
||||
addExtraEmitCodeLine(childName + " = this->invokeChild(_outer." +
|
||||
String(child.fName) + "_index" + inputArg + ", args);");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
|
||||
@ -517,6 +534,14 @@ static const char* glsltype_string(const Context& context, const Type& type) {
|
||||
return "kFloat4_GrSLType";
|
||||
} else if (type == *context.fHalf4_Type) {
|
||||
return "kHalf4_GrSLType";
|
||||
} else if (type == *context.fFloat2x2_Type) {
|
||||
return "kFloat2x2_GrSLType";
|
||||
} else if (type == *context.fHalf2x2_Type) {
|
||||
return "kHalf2x2_GrSLType";
|
||||
} else if (type == *context.fFloat3x3_Type) {
|
||||
return "kFloat3x3_GrSLType";
|
||||
} else if (type == *context.fHalf3x3_Type) {
|
||||
return "kHalf3x3_GrSLType";
|
||||
} else if (type == *context.fFloat4x4_Type) {
|
||||
return "kFloat4x4_GrSLType";
|
||||
} else if (type == *context.fHalf4x4_Type) {
|
||||
@ -1116,13 +1141,13 @@ void CPPCodeGenerator::writeClone() {
|
||||
this->write(" {\n");
|
||||
}
|
||||
this->writef(
|
||||
" auto clone = src.childProcessor(%s_index).clone();\n"
|
||||
" clone->setSampledWithExplicitCoords(\n"
|
||||
" "
|
||||
"src.childProcessor(%s_index).isSampledWithExplicitCoords());\n"
|
||||
" this->registerChildProcessor(std::move(clone));\n"
|
||||
" }\n",
|
||||
fieldName.c_str(), fieldName.c_str());
|
||||
" auto clone = src.childProcessor(%s_index).clone();\n"
|
||||
" if (src.childProcessor(%s_index).isSampledWithExplicitCoords()) {\n"
|
||||
" clone->setSampledWithExplicitCoords();\n"
|
||||
" }"
|
||||
" this->registerChildProcessor(std::move(clone));\n"
|
||||
" }\n",
|
||||
fieldName.c_str(), fieldName.c_str());
|
||||
}
|
||||
}
|
||||
if (samplerCount) {
|
||||
|
@ -396,11 +396,9 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return "<defined>";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> clone() const override {
|
||||
return std::unique_ptr<Expression>(new Defined(fType));
|
||||
|
@ -101,11 +101,9 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String("external<") + fName + ">";
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
typedef Symbol INHERITED;
|
||||
|
@ -284,7 +284,7 @@ void HCodeGenerator::writeConstructor() {
|
||||
this->writef(" %s_index = this->numChildProcessors();",
|
||||
FieldName(String(param->fName).c_str()).c_str());
|
||||
if (fSectionAndParameterHelper.hasCoordOverrides(*param)) {
|
||||
this->writef(" %s->setSampledWithExplicitCoords(true);",
|
||||
this->writef(" %s->setSampledWithExplicitCoords();",
|
||||
String(param->fName).c_str());
|
||||
}
|
||||
this->writef(" this->registerChildProcessor(std::move(%s));",
|
||||
|
34
src/sksl/SkSLSampleMatrix.cpp
Normal file
34
src/sksl/SkSLSampleMatrix.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "src/sksl/SkSLSampleMatrix.h"
|
||||
|
||||
#include "src/sksl/ir/SkSLExpression.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
SampleMatrix SampleMatrix::merge(const SampleMatrix& other) {
|
||||
if (fKind == Kind::kVariable || other.fKind == Kind::kVariable) {
|
||||
*this = SampleMatrix(Kind::kVariable);
|
||||
return *this;
|
||||
}
|
||||
if (other.fKind == Kind::kConstantOrUniform) {
|
||||
if (fKind == other.fKind) {
|
||||
if (fExpression == other.fExpression) {
|
||||
return *this;
|
||||
}
|
||||
*this = SampleMatrix(Kind::kVariable);
|
||||
return *this;
|
||||
}
|
||||
SkASSERT(fKind == Kind::kNone);
|
||||
*this = other;
|
||||
return *this;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace
|
84
src/sksl/SkSLSampleMatrix.h
Normal file
84
src/sksl/SkSLSampleMatrix.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkSLSampleMatrix_DEFINED
|
||||
#define SkSLSampleMatrix_DEFINED
|
||||
|
||||
#include "src/sksl/SkSLDefines.h"
|
||||
#include "src/sksl/SkSLString.h"
|
||||
|
||||
class GrFragmentProcessor;
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
struct Expression;
|
||||
|
||||
/**
|
||||
* Represents the matrix applied to a fragment processor by its parent's sample(child, matrix) call.
|
||||
*/
|
||||
struct SampleMatrix {
|
||||
enum class Kind {
|
||||
// No sample(child, matrix) call affects the FP.
|
||||
kNone,
|
||||
// The FP is sampled with a matrix whose value is fixed and based only on constants or
|
||||
// uniforms, and thus the transform can be hoisted to the vertex shader.
|
||||
kConstantOrUniform,
|
||||
// The FP is sampled with a non-constant/uniform value, or sampled multiple times, and
|
||||
// thus the transform cannot be hoisted to the vertex shader.
|
||||
kVariable,
|
||||
// The FP is sampled with a constant or uniform value, *and* also inherits a variable
|
||||
// transform from an ancestor. The transform cannot be hoisted to the vertex shader, and
|
||||
// both matrices need to be applied.
|
||||
kMixed,
|
||||
};
|
||||
|
||||
SampleMatrix()
|
||||
: fOwner(nullptr)
|
||||
, fKind(Kind::kNone) {}
|
||||
|
||||
SampleMatrix(Kind kind)
|
||||
: fOwner(nullptr)
|
||||
, fKind(kind) {
|
||||
SkASSERT(kind == Kind::kNone || kind == Kind::kVariable);
|
||||
}
|
||||
|
||||
SampleMatrix(Kind kind, GrFragmentProcessor* owner, String expression)
|
||||
: fOwner(owner)
|
||||
, fKind(kind)
|
||||
, fExpression(expression) {}
|
||||
|
||||
SampleMatrix merge(const SampleMatrix& other);
|
||||
|
||||
bool operator==(const SampleMatrix& other) const {
|
||||
return fKind == other.fKind && fExpression == other.fExpression;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() {
|
||||
switch (fKind) {
|
||||
case Kind::kNone:
|
||||
return "SampleMatrix<None>";
|
||||
case Kind::kConstantOrUniform:
|
||||
return "SampleMatrix<ConstantOrUniform(" + fExpression + ")>";
|
||||
case Kind::kVariable:
|
||||
return "SampleMatrix<Variable>";
|
||||
case Kind::kMixed:
|
||||
return "SampleMatrix<Mixed(" + fExpression + ")>";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GrFragmentProcessor* fOwner;
|
||||
Kind fKind;
|
||||
// The constant or uniform expression representing the matrix (will be the empty string when
|
||||
// kind == kNone or kVariable)
|
||||
String fExpression;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
@ -236,4 +236,163 @@ bool SectionAndParameterHelper::hasCoordOverrides(const Statement& s, const Vari
|
||||
return false;
|
||||
}
|
||||
|
||||
SampleMatrix SectionAndParameterHelper::getMatrix(const Variable& fp) {
|
||||
SampleMatrix result;
|
||||
for (const auto& pe : fProgram) {
|
||||
result.merge(this->getMatrix(pe, fp));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
SampleMatrix SectionAndParameterHelper::getMatrix(const ProgramElement& pe, const Variable& fp) {
|
||||
if (pe.fKind == ProgramElement::kFunction_Kind) {
|
||||
return this->getMatrix(*((const FunctionDefinition&) pe).fBody, fp);
|
||||
}
|
||||
return SampleMatrix();
|
||||
}
|
||||
|
||||
SampleMatrix SectionAndParameterHelper::getMatrix(const Expression& e, const Variable& fp) {
|
||||
switch (e.fKind) {
|
||||
case Expression::kFunctionCall_Kind: {
|
||||
const FunctionCall& fc = (const FunctionCall&) e;
|
||||
const FunctionDeclaration& f = fc.fFunction;
|
||||
if (f.fBuiltin && f.fName == "sample" && fc.fArguments.size() >= 2 &&
|
||||
fc.fArguments.back()->fType == *fProgram.fContext->fFloat3x3_Type &&
|
||||
fc.fArguments[0]->fKind == Expression::kVariableReference_Kind &&
|
||||
&((VariableReference&) *fc.fArguments[0]).fVariable == &fp) {
|
||||
if (fc.fArguments.back()->isConstantOrUniform()) {
|
||||
return SampleMatrix(SampleMatrix::Kind::kConstantOrUniform, nullptr,
|
||||
fc.fArguments.back()->description());
|
||||
} else {
|
||||
return SampleMatrix(SampleMatrix::Kind::kVariable);
|
||||
}
|
||||
}
|
||||
SampleMatrix result;
|
||||
for (const auto& e : fc.fArguments) {
|
||||
result.merge(this->getMatrix(*e, fp));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case Expression::kConstructor_Kind: {
|
||||
SampleMatrix result;
|
||||
const Constructor& c = (const Constructor&) e;
|
||||
for (const auto& e : c.fArguments) {
|
||||
result.merge(this->getMatrix(*e, fp));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case Expression::kFieldAccess_Kind: {
|
||||
return this->getMatrix(*((const FieldAccess&) e).fBase, fp);
|
||||
}
|
||||
case Expression::kSwizzle_Kind:
|
||||
return this->getMatrix(*((const Swizzle&) e).fBase, fp);
|
||||
case Expression::kBinary_Kind: {
|
||||
const BinaryExpression& b = (const BinaryExpression&) e;
|
||||
return this->getMatrix(*b.fLeft, fp).merge(this->getMatrix(*b.fRight, fp));
|
||||
}
|
||||
case Expression::kIndex_Kind: {
|
||||
const IndexExpression& idx = (const IndexExpression&) e;
|
||||
return this->getMatrix(*idx.fBase, fp).merge(this->getMatrix(*idx.fIndex, fp));
|
||||
}
|
||||
case Expression::kPrefix_Kind:
|
||||
return this->getMatrix(*((const PrefixExpression&) e).fOperand, fp);
|
||||
case Expression::kPostfix_Kind:
|
||||
return this->getMatrix(*((const PostfixExpression&) e).fOperand, fp);
|
||||
case Expression::kTernary_Kind: {
|
||||
const TernaryExpression& t = (const TernaryExpression&) e;
|
||||
return this->getMatrix(*t.fTest, fp).merge(this->getMatrix(*t.fIfTrue, fp)).merge(
|
||||
this->getMatrix(*t.fIfFalse, fp));
|
||||
}
|
||||
case Expression::kVariableReference_Kind:
|
||||
return SampleMatrix();
|
||||
case Expression::kBoolLiteral_Kind:
|
||||
case Expression::kDefined_Kind:
|
||||
case Expression::kExternalFunctionCall_Kind:
|
||||
case Expression::kExternalValue_Kind:
|
||||
case Expression::kFloatLiteral_Kind:
|
||||
case Expression::kFunctionReference_Kind:
|
||||
case Expression::kIntLiteral_Kind:
|
||||
case Expression::kNullLiteral_Kind:
|
||||
case Expression::kSetting_Kind:
|
||||
case Expression::kTypeReference_Kind:
|
||||
return SampleMatrix();
|
||||
}
|
||||
SkASSERT(false);
|
||||
return SampleMatrix();
|
||||
}
|
||||
|
||||
SampleMatrix SectionAndParameterHelper::getMatrix(const Statement& s, const Variable& fp) {
|
||||
switch (s.fKind) {
|
||||
case Statement::kBlock_Kind: {
|
||||
SampleMatrix result;
|
||||
for (const auto& child : ((const Block&) s).fStatements) {
|
||||
result.merge(this->getMatrix(*child, fp));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case Statement::kVarDeclaration_Kind: {
|
||||
const VarDeclaration& var = (const VarDeclaration&) s;
|
||||
if (var.fValue) {
|
||||
return this->getMatrix(*var.fValue, fp);
|
||||
}
|
||||
return SampleMatrix();
|
||||
}
|
||||
case Statement::kVarDeclarations_Kind: {
|
||||
const VarDeclarations& decls = *((const VarDeclarationsStatement&) s).fDeclaration;
|
||||
SampleMatrix result;
|
||||
for (const auto& stmt : decls.fVars) {
|
||||
result.merge(this->getMatrix(*stmt, fp));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case Statement::kExpression_Kind:
|
||||
return this->getMatrix(*((const ExpressionStatement&) s).fExpression, fp);
|
||||
case Statement::kReturn_Kind: {
|
||||
const ReturnStatement& r = (const ReturnStatement&) s;
|
||||
if (r.fExpression) {
|
||||
return this->getMatrix(*r.fExpression, fp);
|
||||
}
|
||||
return SampleMatrix();
|
||||
}
|
||||
case Statement::kIf_Kind: {
|
||||
const IfStatement& i = (const IfStatement&) s;
|
||||
return this->getMatrix(*i.fTest, fp).merge(this->getMatrix(*i.fIfTrue, fp)).merge(
|
||||
(i.fIfFalse ? this->getMatrix(*i.fIfFalse, fp) : SampleMatrix()));
|
||||
}
|
||||
case Statement::kFor_Kind: {
|
||||
const ForStatement& f = (const ForStatement&) s;
|
||||
return this->getMatrix(*f.fInitializer, fp).merge(
|
||||
this->getMatrix(*f.fTest, fp).merge(
|
||||
this->getMatrix(*f.fNext, fp).merge(
|
||||
this->getMatrix(*f.fStatement, fp))));
|
||||
}
|
||||
case Statement::kWhile_Kind: {
|
||||
const WhileStatement& w = (const WhileStatement&) s;
|
||||
return this->getMatrix(*w.fTest, fp).merge(this->getMatrix(*w.fStatement, fp));
|
||||
}
|
||||
case Statement::kDo_Kind: {
|
||||
const DoStatement& d = (const DoStatement&) s;
|
||||
return this->getMatrix(*d.fTest, fp).merge(this->getMatrix(*d.fStatement, fp));
|
||||
}
|
||||
case Statement::kSwitch_Kind: {
|
||||
SampleMatrix result;
|
||||
const SwitchStatement& sw = (const SwitchStatement&) s;
|
||||
for (const auto& c : sw.fCases) {
|
||||
for (const auto& st : c->fStatements) {
|
||||
result.merge(this->getMatrix(*st, fp));
|
||||
}
|
||||
}
|
||||
return result.merge(this->getMatrix(*sw.fValue, fp));
|
||||
}
|
||||
case Statement::kBreak_Kind:
|
||||
case Statement::kContinue_Kind:
|
||||
case Statement::kDiscard_Kind:
|
||||
case Statement::kGroup_Kind:
|
||||
case Statement::kNop_Kind:
|
||||
return SampleMatrix();
|
||||
}
|
||||
SkASSERT(false);
|
||||
return SampleMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define SKSL_SECTIONANDPARAMETERHELPER
|
||||
|
||||
#include "src/sksl/SkSLErrorReporter.h"
|
||||
#include "src/sksl/SkSLSampleMatrix.h"
|
||||
#include "src/sksl/ir/SkSLProgram.h"
|
||||
#include "src/sksl/ir/SkSLSection.h"
|
||||
#include "src/sksl/ir/SkSLVarDeclarations.h"
|
||||
@ -64,6 +65,8 @@ public:
|
||||
|
||||
bool hasCoordOverrides(const Variable& fp);
|
||||
|
||||
SampleMatrix getMatrix(const Variable& fp);
|
||||
|
||||
static bool IsParameter(const Variable& var) {
|
||||
return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
-1 == var.fModifiers.fLayout.fBuiltin;
|
||||
@ -115,6 +118,12 @@ private:
|
||||
|
||||
bool hasCoordOverrides(const ProgramElement& p, const Variable& fp);
|
||||
|
||||
SampleMatrix getMatrix(const Statement& s, const Variable& fp);
|
||||
|
||||
SampleMatrix getMatrix(const Expression& e, const Variable& fp);
|
||||
|
||||
SampleMatrix getMatrix(const ProgramElement& p, const Variable& fp);
|
||||
|
||||
const Program& fProgram;
|
||||
std::vector<const Variable*> fParameters;
|
||||
std::unordered_map<String, std::vector<const Section*>> fSections;
|
||||
|
@ -27,6 +27,10 @@ struct BinaryExpression : public Expression {
|
||||
, fOperator(op)
|
||||
, fRight(std::move(right)) {}
|
||||
|
||||
bool isConstantOrUniform() const override {
|
||||
return fLeft->isConstantOrUniform() && fRight->isConstantOrUniform();
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
|
||||
const DefinitionMap& definitions) override {
|
||||
return irGenerator.constantFold(*fLeft,
|
||||
@ -46,12 +50,10 @@ struct BinaryExpression : public Expression {
|
||||
fRight->clone(), fType));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
|
||||
fRight->description() + ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fLeft;
|
||||
const Token::Kind fOperator;
|
||||
|
@ -40,7 +40,6 @@ struct Block : public Statement {
|
||||
return std::unique_ptr<Statement>(new Block(fOffset, std::move(cloned), fSymbols));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result("{");
|
||||
for (size_t i = 0; i < fStatements.size(); i++) {
|
||||
@ -50,7 +49,6 @@ struct Block : public Statement {
|
||||
result += "\n}\n";
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// it's important to keep fStatements defined after (and thus destroyed before) fSymbols,
|
||||
// because destroying statements can modify reference counts in symbols
|
||||
|
@ -21,11 +21,9 @@ struct BoolLiteral : public Expression {
|
||||
: INHERITED(offset, kBoolLiteral_Kind, *context.fBool_Type)
|
||||
, fValue(value) {}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String(fValue ? "true" : "false");
|
||||
}
|
||||
#endif
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
return false;
|
||||
|
@ -24,11 +24,9 @@ struct BreakStatement : public Statement {
|
||||
return std::unique_ptr<Statement>(new BreakStatement(fOffset));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String("break;");
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef Statement INHERITED;
|
||||
};
|
||||
|
@ -67,7 +67,6 @@ struct Constructor : public Expression {
|
||||
return std::unique_ptr<Expression>(new Constructor(fOffset, fType, std::move(cloned)));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result = fType.description() + "(";
|
||||
String separator;
|
||||
@ -79,7 +78,6 @@ struct Constructor : public Expression {
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isConstant() const override {
|
||||
for (size_t i = 0; i < fArguments.size(); i++) {
|
||||
@ -90,6 +88,15 @@ struct Constructor : public Expression {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isConstantOrUniform() const override {
|
||||
for (size_t i = 0; i < fArguments.size(); i++) {
|
||||
if (!fArguments[i]->isConstantOrUniform()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compareConstant(const Context& context, const Expression& other) const override {
|
||||
SkASSERT(other.fKind == Expression::kConstructor_Kind && other.fType == fType);
|
||||
Constructor& c = (Constructor&) other;
|
||||
|
@ -24,11 +24,9 @@ struct ContinueStatement : public Statement {
|
||||
return std::unique_ptr<Statement>(new ContinueStatement(fOffset));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String("continue;");
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef Statement INHERITED;
|
||||
};
|
||||
|
@ -24,11 +24,9 @@ struct DiscardStatement : public Statement {
|
||||
return std::unique_ptr<Statement>(new DiscardStatement(fOffset));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String("discard;");
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef Statement INHERITED;
|
||||
};
|
||||
|
@ -28,11 +28,9 @@ struct DoStatement : public Statement {
|
||||
fTest->clone()));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return "do " + fStatement->description() + " while (" + fTest->description() + ");";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Statement> fStatement;
|
||||
std::unique_ptr<Expression> fTest;
|
||||
|
@ -50,11 +50,9 @@ struct Enum : public ProgramElement {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return this->code();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool fBuiltin = false;
|
||||
const StringFragment fTypeName;
|
||||
|
@ -90,6 +90,15 @@ struct Expression : public IRNode {
|
||||
ABORT("not a constant float");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if, given fixed values for uniforms, this expression always evaluates to the
|
||||
* same result with no side effects.
|
||||
*/
|
||||
virtual bool isConstantOrUniform() const {
|
||||
SkASSERT(!this->isConstant() || !this->hasSideEffects());
|
||||
return this->isConstant();
|
||||
}
|
||||
|
||||
virtual bool hasProperty(Property property) const = 0;
|
||||
|
||||
bool hasSideEffects() const {
|
||||
|
@ -25,11 +25,9 @@ struct ExpressionStatement : public Statement {
|
||||
return std::unique_ptr<Statement>(new ExpressionStatement(fExpression->clone()));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fExpression->description() + ";";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fExpression;
|
||||
|
||||
|
@ -24,11 +24,9 @@ struct Extension : public ProgramElement {
|
||||
return std::unique_ptr<ProgramElement>(new Extension(fOffset, fName));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return "#extension " + fName + " : enable";
|
||||
}
|
||||
#endif
|
||||
|
||||
const String fName;
|
||||
|
||||
|
@ -47,7 +47,6 @@ struct ExternalFunctionCall : public Expression {
|
||||
std::move(cloned)));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result = String(fFunction->fName) + "(";
|
||||
String separator;
|
||||
@ -59,7 +58,6 @@ struct ExternalFunctionCall : public Expression {
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
ExternalValue* fFunction;
|
||||
std::vector<std::unique_ptr<Expression>> fArguments;
|
||||
|
@ -25,11 +25,9 @@ struct ExternalValueReference : public Expression {
|
||||
return property == Property::kSideEffects;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String(fValue->fName);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> clone() const override {
|
||||
return std::unique_ptr<Expression>(new ExternalValueReference(fOffset, fValue));
|
||||
|
@ -27,11 +27,9 @@ struct Field : public Symbol {
|
||||
, fOwner(owner)
|
||||
, fFieldIndex(fieldIndex) {}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
virtual String description() const override {
|
||||
return fOwner.description() + "." + fOwner.fType.fields()[fFieldIndex].fName;
|
||||
}
|
||||
#endif
|
||||
|
||||
const Variable& fOwner;
|
||||
const int fFieldIndex;
|
||||
|
@ -40,11 +40,9 @@ struct FieldAccess : public Expression {
|
||||
fOwnerKind));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fBase->description() + "." + fBase->fType.fields()[fFieldIndex].fName;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fBase;
|
||||
const int fFieldIndex;
|
||||
|
@ -25,11 +25,9 @@ struct FloatLiteral : public Expression {
|
||||
: INHERITED(offset, kFloatLiteral_Kind, *type)
|
||||
, fValue(value) {}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return to_string(fValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
return false;
|
||||
|
@ -34,7 +34,6 @@ struct ForStatement : public Statement {
|
||||
fStatement->clone(), fSymbols));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result("for (");
|
||||
if (fInitializer) {
|
||||
@ -51,7 +50,6 @@ struct ForStatement : public Statement {
|
||||
result += ") " + fStatement->description();
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// it's important to keep fSymbols defined first (and thus destroyed last) because destroying
|
||||
// the other fields can update symbol reference counts
|
||||
|
@ -45,7 +45,6 @@ struct FunctionCall : public Expression {
|
||||
std::move(cloned)));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result = String(fFunction.fName) + "(";
|
||||
String separator;
|
||||
@ -57,7 +56,6 @@ struct FunctionCall : public Expression {
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
const FunctionDeclaration& fFunction;
|
||||
std::vector<std::unique_ptr<Expression>> fArguments;
|
||||
|
@ -42,11 +42,9 @@ struct FunctionDeclaration : public Symbol {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return this->declaration();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool matches(const FunctionDeclaration& f) const {
|
||||
if (fName != f.fName) {
|
||||
|
@ -31,11 +31,9 @@ struct FunctionDefinition : public ProgramElement {
|
||||
fBody->clone()));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fDeclaration.description() + " " + fBody->description();
|
||||
}
|
||||
#endif
|
||||
|
||||
const FunctionDeclaration& fDeclaration;
|
||||
std::unique_ptr<Statement> fBody;
|
||||
|
@ -32,11 +32,9 @@ struct FunctionReference : public Expression {
|
||||
return std::unique_ptr<Expression>(new FunctionReference(fOffset, fFunctions, &fType));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String("<function>");
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::vector<const FunctionDeclaration*> fFunctions;
|
||||
|
||||
|
@ -23,9 +23,7 @@ struct IRNode {
|
||||
|
||||
virtual ~IRNode() {}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
virtual String description() const = 0;
|
||||
#endif
|
||||
|
||||
// character offset of this element within the program being compiled, for error reporting
|
||||
// purposes
|
||||
|
@ -30,7 +30,6 @@ struct IfStatement : public Statement {
|
||||
fIfTrue->clone(), fIfFalse ? fIfFalse->clone() : nullptr));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result;
|
||||
if (fIsStatic) {
|
||||
@ -42,7 +41,6 @@ struct IfStatement : public Statement {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool fIsStatic;
|
||||
std::unique_ptr<Expression> fTest;
|
||||
|
@ -67,11 +67,9 @@ struct IndexExpression : public Expression {
|
||||
&fType));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fBase->description() + "[" + fIndex->description() + "]";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fBase;
|
||||
std::unique_ptr<Expression> fIndex;
|
||||
|
@ -27,11 +27,9 @@ struct IntLiteral : public Expression {
|
||||
: INHERITED(offset, kIntLiteral_Kind, *type)
|
||||
, fValue(value) {}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return to_string(fValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
return false;
|
||||
|
@ -46,7 +46,6 @@ struct InterfaceBlock : public ProgramElement {
|
||||
fTypeOwner));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result = fVariable.fModifiers.description() + fTypeName + " {\n";
|
||||
const Type* structType = &fVariable.fType;
|
||||
@ -69,7 +68,6 @@ struct InterfaceBlock : public ProgramElement {
|
||||
}
|
||||
return result + ";";
|
||||
}
|
||||
#endif
|
||||
|
||||
const Variable& fVariable;
|
||||
const String fTypeName;
|
||||
|
@ -27,11 +27,9 @@ struct ModifiersDeclaration : public ProgramElement {
|
||||
return std::unique_ptr<ProgramElement>(new ModifiersDeclaration(fModifiers));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fModifiers.description() + ";";
|
||||
}
|
||||
#endif
|
||||
|
||||
Modifiers fModifiers;
|
||||
|
||||
|
@ -24,11 +24,9 @@ struct Nop : public Statement {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String(";");
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Statement> clone() const override {
|
||||
return std::unique_ptr<Statement>(new Nop());
|
||||
|
@ -23,11 +23,9 @@ struct NullLiteral : public Expression {
|
||||
NullLiteral(int offset, const Type& type)
|
||||
: INHERITED(offset, kNullLiteral_Kind, type) {}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return "null";
|
||||
}
|
||||
#endif
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
return false;
|
||||
|
@ -34,11 +34,9 @@ struct PostfixExpression : public Expression {
|
||||
return std::unique_ptr<Expression>(new PostfixExpression(fOperand->clone(), fOperator));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fOperand->description() + Compiler::OperatorName(fOperator);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fOperand;
|
||||
const Token::Kind fOperator;
|
||||
|
@ -68,11 +68,9 @@ struct PrefixExpression : public Expression {
|
||||
return std::unique_ptr<Expression>(new PrefixExpression(fOperator, fOperand->clone()));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return Compiler::OperatorName(fOperator) + fOperand->description();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fOperand;
|
||||
const Token::Kind fOperator;
|
||||
|
@ -31,7 +31,6 @@ struct ReturnStatement : public Statement {
|
||||
return std::unique_ptr<Statement>(new ReturnStatement(fOffset));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
if (fExpression) {
|
||||
return "return " + fExpression->description() + ";";
|
||||
@ -39,7 +38,6 @@ struct ReturnStatement : public Statement {
|
||||
return String("return;");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fExpression;
|
||||
|
||||
|
@ -26,7 +26,6 @@ struct Section : public ProgramElement {
|
||||
return std::unique_ptr<ProgramElement>(new Section(fOffset, fName, fArgument, fText));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result = "@" + fName;
|
||||
if (fArgument.size()) {
|
||||
@ -35,7 +34,6 @@ struct Section : public ProgramElement {
|
||||
result += " { " + fText + " }";
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
const String fName;
|
||||
const String fArgument;
|
||||
|
@ -32,11 +32,9 @@ struct Setting : public Expression {
|
||||
return std::unique_ptr<Expression>(new Setting(fOffset, fName, fValue->clone()));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fName;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
return false;
|
||||
|
@ -33,7 +33,6 @@ struct SwitchCase : public Statement {
|
||||
std::move(cloned)));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result;
|
||||
if (fValue) {
|
||||
@ -46,7 +45,6 @@ struct SwitchCase : public Statement {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// null value implies "default" case
|
||||
std::unique_ptr<Expression> fValue;
|
||||
|
@ -37,7 +37,6 @@ struct SwitchStatement : public Statement {
|
||||
std::move(cloned), fSymbols));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result;
|
||||
if (fIsStatic) {
|
||||
@ -50,7 +49,6 @@ struct SwitchStatement : public Statement {
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool fIsStatic;
|
||||
std::unique_ptr<Expression> fValue;
|
||||
|
@ -140,7 +140,6 @@ struct Swizzle : public Expression {
|
||||
return std::unique_ptr<Expression>(new Swizzle(fType, fBase->clone(), fComponents));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result = fBase->description() + ".";
|
||||
for (int x : fComponents) {
|
||||
@ -148,7 +147,6 @@ struct Swizzle : public Expression {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fBase;
|
||||
std::vector<int> fComponents;
|
||||
|
@ -31,18 +31,21 @@ struct TernaryExpression : public Expression {
|
||||
fIfFalse->hasProperty(property);
|
||||
}
|
||||
|
||||
bool isConstantOrUniform() const override {
|
||||
return fTest->isConstantOrUniform() && fIfTrue->isConstantOrUniform() &&
|
||||
fIfFalse->isConstantOrUniform();
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> clone() const override {
|
||||
return std::unique_ptr<Expression>(new TernaryExpression(fOffset, fTest->clone(),
|
||||
fIfTrue->clone(),
|
||||
fIfFalse->clone()));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return "(" + fTest->description() + " ? " + fIfTrue->description() + " : " +
|
||||
fIfFalse->description() + ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> fTest;
|
||||
std::unique_ptr<Expression> fIfTrue;
|
||||
|
@ -242,11 +242,9 @@ public:
|
||||
return fNameString;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return this->displayName();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator==(const Type& other) const {
|
||||
return fName == other.fName;
|
||||
|
@ -26,11 +26,9 @@ struct TypeReference : public Expression {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return String(fValue.fName);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Expression> clone() const override {
|
||||
return std::unique_ptr<Expression>(new TypeReference(fOffset, fValue, &fType));
|
||||
|
@ -26,11 +26,9 @@ struct UnresolvedFunction : public Symbol {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
return fName;
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::vector<const FunctionDeclaration*> fFunctions;
|
||||
|
||||
|
@ -42,7 +42,6 @@ struct VarDeclaration : public Statement {
|
||||
fValue ? fValue->clone() : nullptr));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
String result = fVar->fName;
|
||||
for (const auto& size : fSizes) {
|
||||
@ -57,7 +56,6 @@ struct VarDeclaration : public Statement {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
const Variable* fVar;
|
||||
std::vector<std::unique_ptr<Expression>> fSizes;
|
||||
@ -89,7 +87,6 @@ struct VarDeclarations : public ProgramElement {
|
||||
std::move(cloned)));
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
String description() const override {
|
||||
if (!fVars.size()) {
|
||||
return String();
|
||||
@ -104,7 +101,6 @@ struct VarDeclarations : public ProgramElement {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
const Type& fBaseType;
|
||||
// this *should* be a vector of unique_ptr<VarDeclaration>, but it significantly simplifies the
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user