Remove fExpression (matrix expression) from SampleUsage
Other than GMs, there is exactly one use of matrix-sampling (GrMatrixEffect). It is always uniform (not literal or an expression containing a uniform). The uniform always has the same name. Bake these simplifications in, which also shrinks SampleUsage quite a bit. Change-Id: I0d5e32069d710af475ccc1030e2988c5fc965a98 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/411296 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
50cc5d4147
commit
b1e9cb08c1
@ -14,37 +14,6 @@
|
||||
#include "src/gpu/ops/GrFillRectOp.h"
|
||||
#include "tools/ToolUtils.h"
|
||||
|
||||
// Samples child with a constant (literal) matrix
|
||||
// Scales along X
|
||||
class ConstantMatrixEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static constexpr GrProcessor::ClassID CLASS_ID = (GrProcessor::ClassID) 3;
|
||||
|
||||
ConstantMatrixEffect(std::unique_ptr<GrFragmentProcessor> child)
|
||||
: GrFragmentProcessor(CLASS_ID, kNone_OptimizationFlags) {
|
||||
this->registerChild(std::move(child),
|
||||
SkSL::SampleUsage::UniformMatrix(
|
||||
"float3x3(float3(0.5, 0.0, 0.0), "
|
||||
"float3(0.0, 1.0, 0.0), "
|
||||
"float3(0.0, 0.0, 1.0))"));
|
||||
}
|
||||
|
||||
const char* name() const override { return "ConstantMatrixEffect"; }
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
|
||||
bool onIsEqual(const GrFragmentProcessor& that) const override { return this == &that; }
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override { return nullptr; }
|
||||
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override {
|
||||
class Impl : public GrGLSLFragmentProcessor {
|
||||
void emitCode(EmitArgs& args) override {
|
||||
SkString sample = this->invokeChildWithMatrix(0, args);
|
||||
args.fFragBuilder->codeAppendf("return %s;\n", sample.c_str());
|
||||
}
|
||||
};
|
||||
return std::make_unique<Impl>();
|
||||
}
|
||||
};
|
||||
|
||||
// Samples child with a uniform matrix (functionally identical to GrMatrixEffect)
|
||||
// Scales along Y
|
||||
class UniformMatrixEffect : public GrFragmentProcessor {
|
||||
@ -53,7 +22,8 @@ public:
|
||||
|
||||
UniformMatrixEffect(std::unique_ptr<GrFragmentProcessor> child)
|
||||
: GrFragmentProcessor(CLASS_ID, kNone_OptimizationFlags) {
|
||||
this->registerChild(std::move(child), SkSL::SampleUsage::UniformMatrix("matrix"));
|
||||
this->registerChild(std::move(child),
|
||||
SkSL::SampleUsage::UniformMatrix(/*hasPerspective=*/false));
|
||||
}
|
||||
|
||||
const char* name() const override { return "UniformMatrixEffect"; }
|
||||
@ -64,8 +34,11 @@ public:
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override {
|
||||
class Impl : public GrGLSLFragmentProcessor {
|
||||
void emitCode(EmitArgs& args) override {
|
||||
fMatrixVar = args.fUniformHandler->addUniform(&args.fFp, kFragment_GrShaderFlag,
|
||||
kFloat3x3_GrSLType, "matrix");
|
||||
fMatrixVar =
|
||||
args.fUniformHandler->addUniform(&args.fFp,
|
||||
kFragment_GrShaderFlag,
|
||||
kFloat3x3_GrSLType,
|
||||
SkSL::SampleUsage::MatrixUniformName());
|
||||
SkString sample = this->invokeChildWithMatrix(0, args);
|
||||
args.fFragBuilder->codeAppendf("return %s;\n", sample.c_str());
|
||||
}
|
||||
@ -160,7 +133,6 @@ SkBitmap make_test_bitmap() {
|
||||
}
|
||||
|
||||
enum EffectType {
|
||||
kConstant,
|
||||
kUniform,
|
||||
kExplicit,
|
||||
};
|
||||
@ -168,8 +140,6 @@ enum EffectType {
|
||||
static std::unique_ptr<GrFragmentProcessor> wrap(std::unique_ptr<GrFragmentProcessor> fp,
|
||||
EffectType effectType) {
|
||||
switch (effectType) {
|
||||
case kConstant:
|
||||
return std::make_unique<ConstantMatrixEffect>(std::move(fp));
|
||||
case kUniform:
|
||||
return std::make_unique<UniformMatrixEffect>(std::move(fp));
|
||||
case kExplicit:
|
||||
@ -178,7 +148,7 @@ static std::unique_ptr<GrFragmentProcessor> wrap(std::unique_ptr<GrFragmentProce
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GPU_GM(fp_sample_chaining, ctx, rtCtx, canvas, 306, 232) {
|
||||
DEF_SIMPLE_GPU_GM(fp_sample_chaining, ctx, rtCtx, canvas, 232, 232) {
|
||||
SkBitmap bmp = make_test_bitmap();
|
||||
|
||||
int x = 10, y = 10;
|
||||
@ -212,21 +182,16 @@ DEF_SIMPLE_GPU_GM(fp_sample_chaining, ctx, rtCtx, canvas, 306, 232) {
|
||||
|
||||
// First row: no transform, then each one independently applied
|
||||
draw({}); // Identity (4 rows and columns)
|
||||
draw({ kConstant }); // Scale X axis by 2x (2 visible columns)
|
||||
draw({ kUniform }); // Scale Y axis by 2x (2 visible rows)
|
||||
draw({ kExplicit }); // Translate up by 8px
|
||||
nextRow();
|
||||
|
||||
// Second row: transform duplicated
|
||||
draw({ kConstant, kUniform }); // Scale XY by 2x (2 rows and columns)
|
||||
draw({ kConstant, kConstant }); // Scale X axis by 4x (1 visible column)
|
||||
draw({ kUniform, kUniform }); // Scale Y axis by 4x (1 visible row)
|
||||
draw({ kExplicit, kExplicit }); // Translate up by 16px
|
||||
nextRow();
|
||||
|
||||
// Remember, these are applied inside out:
|
||||
draw({ kConstant, kExplicit }); // Scale X by 2x and translate up by 8px
|
||||
draw({ kUniform, kExplicit }); // Scale Y by 2x and translate up by 8px
|
||||
draw({ kExplicit, kExplicit, kConstant }); // Scale X by 2x and translate up by 16px
|
||||
draw({ kExplicit, kUniform }); // Scale Y by 2x and translate up by 16px
|
||||
draw({ kExplicit, kUniform }); // Scale Y by 2x and translate up by 16px
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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/core/SkMatrixProvider.h"
|
||||
#include "src/gpu/GrDirectContextPriv.h"
|
||||
#include "src/gpu/SkGr.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) {
|
||||
this->registerChild(std::move(child),
|
||||
SkSL::SampleUsage::UniformMatrix(
|
||||
"float3x3(float3(0.5, 0.0, 0.0), "
|
||||
"float3(0.0, 0.5, 0.0), "
|
||||
"float3(0.0, 0.0, 1.0))"));
|
||||
}
|
||||
|
||||
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:
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
|
||||
using INHERITED = GrFragmentProcessor;
|
||||
};
|
||||
|
||||
class GLSLSampleMatrixConstantEffect : public GrGLSLFragmentProcessor {
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkString sample = this->invokeChildWithMatrix(0, args);
|
||||
fragBuilder->codeAppendf("return %s;\n", sample.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> SampleMatrixConstantEffect::onMakeProgramImpl() const {
|
||||
return std::make_unique<GLSLSampleMatrixConstantEffect>();
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GPU_GM(sample_matrix_constant, ctx, rtCtx, canvas, 1024, 256) {
|
||||
auto wrap = [](std::unique_ptr<GrFragmentProcessor> baseFP) {
|
||||
return std::unique_ptr<GrFragmentProcessor>(
|
||||
new SampleMatrixConstantEffect(std::move(baseFP)));
|
||||
};
|
||||
auto draw = [rtCtx, &wrap](std::unique_ptr<GrFragmentProcessor> baseFP, int tx, int ty) {
|
||||
auto fp = wrap(std::move(baseFP));
|
||||
GrPaint paint;
|
||||
paint.setColorFragmentProcessor(std::move(fp));
|
||||
rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::Translate(tx, ty),
|
||||
SkRect::MakeIWH(256, 256));
|
||||
};
|
||||
auto draw2 = [rtCtx, &wrap](std::unique_ptr<GrFragmentProcessor> baseFP, int tx, int ty) {
|
||||
auto fp = wrap(wrap(std::move(baseFP)));
|
||||
GrPaint paint;
|
||||
paint.setColorFragmentProcessor(std::move(fp));
|
||||
rtCtx->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::Translate(tx, ty),
|
||||
SkRect::MakeIWH(256, 256));
|
||||
};
|
||||
|
||||
{
|
||||
SkBitmap bmp;
|
||||
GetResourceAsBitmap("images/mandrill_256.png", &bmp);
|
||||
auto [view, ct] = GrMakeCachedBitmapProxyView(ctx, bmp, GrMipmapped::kNo);
|
||||
std::unique_ptr<GrFragmentProcessor> imgFP = GrTextureEffect::Make(view,
|
||||
bmp.alphaType(),
|
||||
SkMatrix());
|
||||
draw(std::move(imgFP), 0, 0);
|
||||
imgFP = GrTextureEffect::Make(std::move(view), bmp.alphaType(), SkMatrix());
|
||||
draw2(std::move(imgFP), 256, 0);
|
||||
}
|
||||
|
||||
{
|
||||
static constexpr SkColor colors[] = { 0xff00ff00, 0xffff00ff };
|
||||
const SkPoint pts[] = {{ 0, 0 }, { 256, 0 }};
|
||||
|
||||
auto shader = SkGradientShader::MakeLinear(pts, colors, nullptr,
|
||||
SK_ARRAY_COUNT(colors),
|
||||
SkTileMode::kClamp);
|
||||
SkMatrix matrix;
|
||||
SkSimpleMatrixProvider matrixProvider(matrix);
|
||||
GrColorInfo colorInfo;
|
||||
GrFPArgs args(ctx, matrixProvider, &colorInfo);
|
||||
std::unique_ptr<GrFragmentProcessor> gradientFP = as_SB(shader)->asFragmentProcessor(args);
|
||||
draw(std::move(gradientFP), 512, 0);
|
||||
gradientFP = as_SB(shader)->asFragmentProcessor(args);
|
||||
draw2(std::move(gradientFP), 768, 0);
|
||||
}
|
||||
}
|
@ -326,7 +326,6 @@ gm_sources = [
|
||||
"$_gm/runtimefunctions.cpp",
|
||||
"$_gm/runtimeintrinsics.cpp",
|
||||
"$_gm/runtimeshader.cpp",
|
||||
"$_gm/sample_matrix_constant.cpp",
|
||||
"$_gm/samplerstress.cpp",
|
||||
"$_gm/savelayer.cpp",
|
||||
"$_gm/scaledemoji.cpp",
|
||||
|
@ -32,18 +32,20 @@ struct SampleUsage {
|
||||
// Make a SampleUsage that corresponds to no sampling of the child at all
|
||||
SampleUsage() = default;
|
||||
|
||||
// Child is sampled with a matrix whose value is uniform (some expression only involving
|
||||
// literals and uniform variables).
|
||||
static SampleUsage UniformMatrix(std::string expression, bool hasPerspective = true) {
|
||||
return SampleUsage(Kind::kUniformMatrix, std::move(expression), hasPerspective);
|
||||
// Child is sampled with a matrix whose value is uniform. The name is fixed.
|
||||
static SampleUsage UniformMatrix(bool hasPerspective) {
|
||||
return SampleUsage(Kind::kUniformMatrix, hasPerspective);
|
||||
}
|
||||
|
||||
// Arbitrary name used by all uniform sampling matrices
|
||||
static const char* MatrixUniformName() { return "matrix"; }
|
||||
|
||||
static SampleUsage Explicit() {
|
||||
return SampleUsage(Kind::kExplicit, "", false);
|
||||
return SampleUsage(Kind::kExplicit, false);
|
||||
}
|
||||
|
||||
static SampleUsage PassThrough() {
|
||||
return SampleUsage(Kind::kPassThrough, "", false);
|
||||
return SampleUsage(Kind::kPassThrough, false);
|
||||
}
|
||||
|
||||
SampleUsage merge(const SampleUsage& other);
|
||||
@ -54,16 +56,11 @@ struct SampleUsage {
|
||||
bool isUniformMatrix() const { return fKind == Kind::kUniformMatrix; }
|
||||
|
||||
Kind fKind = Kind::kNone;
|
||||
// The uniform expression representing the matrix, or empty for non-matrix sampling
|
||||
std::string fExpression;
|
||||
bool fHasPerspective = false;
|
||||
bool fHasPerspective = false; // Only valid if fKind is kUniformMatrix
|
||||
|
||||
SampleUsage(Kind kind, std::string expression, bool hasPerspective)
|
||||
: fKind(kind), fExpression(expression), fHasPerspective(hasPerspective) {
|
||||
if (kind == Kind::kUniformMatrix) {
|
||||
SkASSERT(!fExpression.empty());
|
||||
} else {
|
||||
SkASSERT(fExpression.empty() && !fHasPerspective);
|
||||
SampleUsage(Kind kind, bool hasPerspective) : fKind(kind), fHasPerspective(hasPerspective) {
|
||||
if (kind != Kind::kUniformMatrix) {
|
||||
SkASSERT(!fHasPerspective);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,10 @@ public:
|
||||
GrGLSLMatrixEffect() {}
|
||||
|
||||
void emitCode(EmitArgs& args) override {
|
||||
fMatrixVar = args.fUniformHandler->addUniform(&args.fFp, kFragment_GrShaderFlag,
|
||||
kFloat3x3_GrSLType, "matrix");
|
||||
fMatrixVar = args.fUniformHandler->addUniform(&args.fFp,
|
||||
kFragment_GrShaderFlag,
|
||||
kFloat3x3_GrSLType,
|
||||
SkSL::SampleUsage::MatrixUniformName());
|
||||
args.fFragBuilder->codeAppendf("return %s;\n",
|
||||
this->invokeChildWithMatrix(0, args).c_str());
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ private:
|
||||
, fMatrix(matrix) {
|
||||
SkASSERT(child);
|
||||
this->registerChild(std::move(child),
|
||||
SkSL::SampleUsage::UniformMatrix("matrix", matrix.hasPerspective()));
|
||||
SkSL::SampleUsage::UniformMatrix(matrix.hasPerspective()));
|
||||
}
|
||||
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
|
||||
|
@ -87,24 +87,17 @@ SkString GrGLSLFragmentProcessor::invokeChildWithMatrix(int childIndex, const ch
|
||||
|
||||
SkASSERT(childProc->sampleUsage().isUniformMatrix());
|
||||
|
||||
// Empty matrix expression replaces with the sample matrix expression stored on the FP, but
|
||||
// that is only valid for uniform sampled FPs
|
||||
SkString matrixExpr(childProc->sampleUsage().fExpression);
|
||||
|
||||
// Attempt to resolve the uniform name from the raw name stored in the sample usage.
|
||||
// Every uniform matrix has the same (initial) name. Resolve that into the mangled name:
|
||||
GrShaderVar uniform = args.fUniformHandler->getUniformMapping(
|
||||
args.fFp, SkString(childProc->sampleUsage().fExpression));
|
||||
if (uniform.getType() != kVoid_GrSLType) {
|
||||
// Found the uniform, so replace the expression with the actual uniform name
|
||||
SkASSERT(uniform.getType() == kFloat3x3_GrSLType);
|
||||
matrixExpr = uniform.getName().c_str();
|
||||
} // else assume it's a constant expression
|
||||
args.fFp, SkString(SkSL::SampleUsage::MatrixUniformName()));
|
||||
SkASSERT(uniform.getType() == kFloat3x3_GrSLType);
|
||||
const SkString& matrixName(uniform.getName());
|
||||
|
||||
// Produce a string containing the call to the helper function. We have a const-or-uniform
|
||||
// expression containing our transform (matrixExpr). If the parent coords were produced by
|
||||
// uniform transforms, then the entire expression (matrixExpr * coords) is lifted to a vertex
|
||||
// shader and is stored in a varying. In that case, childProc will not be sampled explicitly,
|
||||
// so its function signature will not take in coords.
|
||||
// Produce a string containing the call to the helper function. We have a uniform variable
|
||||
// containing our transform (matrixName). If the parent coords were produced by uniform
|
||||
// transforms, then the entire expression (matrixName * coords) is lifted to a vertex shader
|
||||
// and is stored in a varying. In that case, childProc will not be sampled explicitly, so its
|
||||
// function signature will not take in coords.
|
||||
//
|
||||
// In all other cases, we need to insert sksl to compute matrix * parent coords and then invoke
|
||||
// the function.
|
||||
@ -113,14 +106,14 @@ SkString GrGLSLFragmentProcessor::invokeChildWithMatrix(int childIndex, const ch
|
||||
// Any parent perspective will have already been applied when evaluated in the FS.
|
||||
if (childProc->sampleUsage().fHasPerspective) {
|
||||
return SkStringPrintf("%s(%s, proj((%s) * %s.xy1))", fFunctionNames[childIndex].c_str(),
|
||||
inputColor, matrixExpr.c_str(), args.fSampleCoord);
|
||||
inputColor, matrixName.c_str(), args.fSampleCoord);
|
||||
} else if (args.fShaderCaps->nonsquareMatrixSupport()) {
|
||||
return SkStringPrintf("%s(%s, float3x2(%s) * %s.xy1)",
|
||||
fFunctionNames[childIndex].c_str(), inputColor,
|
||||
matrixExpr.c_str(), args.fSampleCoord);
|
||||
matrixName.c_str(), args.fSampleCoord);
|
||||
} else {
|
||||
return SkStringPrintf("%s(%s, ((%s) * %s.xy1).xy)", fFunctionNames[childIndex].c_str(),
|
||||
inputColor, matrixExpr.c_str(), args.fSampleCoord);
|
||||
inputColor, matrixName.c_str(), args.fSampleCoord);
|
||||
}
|
||||
} else {
|
||||
// Since this is uniform and not explicitly sampled, it's transform has been promoted to
|
||||
|
@ -187,25 +187,16 @@ void GrGLSLGeometryProcessor::emitTransformCode(GrGLSLVertexBuilder* vb,
|
||||
}
|
||||
break;
|
||||
} else if (base->sampleUsage().isUniformMatrix()) {
|
||||
// The FP knows the matrix expression it's sampled with, but its parent defined
|
||||
// the uniform (when the expression is not a constant).
|
||||
// The matrix expression is always the same, but the parent defined the uniform
|
||||
GrShaderVar uniform = uniformHandler->liftUniformToVertexShader(
|
||||
*base->parent(), SkString(base->sampleUsage().fExpression));
|
||||
*base->parent(), SkString(SkSL::SampleUsage::MatrixUniformName()));
|
||||
SkASSERT(uniform.getType() == kFloat3x3_GrSLType);
|
||||
|
||||
// Accumulate the base matrix expression as a preConcat
|
||||
SkString matrix;
|
||||
if (uniform.getType() != kVoid_GrSLType) {
|
||||
SkASSERT(uniform.getType() == kFloat3x3_GrSLType);
|
||||
matrix = uniform.getName();
|
||||
} else {
|
||||
// No uniform found, so presumably this is a constant
|
||||
matrix = SkString(base->sampleUsage().fExpression);
|
||||
}
|
||||
|
||||
if (!transformExpression.isEmpty()) {
|
||||
transformExpression.append(" * ");
|
||||
}
|
||||
transformExpression.appendf("(%s)", matrix.c_str());
|
||||
transformExpression.appendf("(%s)", uniform.getName().c_str());
|
||||
} else {
|
||||
// This intermediate FP is just a pass through and doesn't need to be built
|
||||
// in to the expression, but must visit its parents in case they add transforms
|
||||
|
@ -7,24 +7,7 @@
|
||||
|
||||
#include "include/private/SkSLSampleUsage.h"
|
||||
|
||||
#include "src/sksl/ir/SkSLBinaryExpression.h"
|
||||
#include "src/sksl/ir/SkSLConstructor.h"
|
||||
#include "src/sksl/ir/SkSLDoStatement.h"
|
||||
#include "src/sksl/ir/SkSLExpression.h"
|
||||
#include "src/sksl/ir/SkSLExpressionStatement.h"
|
||||
#include "src/sksl/ir/SkSLFieldAccess.h"
|
||||
#include "src/sksl/ir/SkSLForStatement.h"
|
||||
#include "src/sksl/ir/SkSLFunctionCall.h"
|
||||
#include "src/sksl/ir/SkSLIfStatement.h"
|
||||
#include "src/sksl/ir/SkSLIndexExpression.h"
|
||||
#include "src/sksl/ir/SkSLPostfixExpression.h"
|
||||
#include "src/sksl/ir/SkSLPrefixExpression.h"
|
||||
#include "src/sksl/ir/SkSLProgram.h"
|
||||
#include "src/sksl/ir/SkSLReturnStatement.h"
|
||||
#include "src/sksl/ir/SkSLSwitchStatement.h"
|
||||
#include "src/sksl/ir/SkSLSwizzle.h"
|
||||
#include "src/sksl/ir/SkSLTernaryExpression.h"
|
||||
#include "src/sksl/ir/SkSLVariable.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user