skia2/include/effects/SkRuntimeEffect.h

423 lines
16 KiB
C
Raw Normal View History

/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkRuntimeEffect_DEFINED
#define SkRuntimeEffect_DEFINED
#include "include/core/SkColorFilter.h"
#include "include/core/SkData.h"
Reland "Remove (unused) gpuType from SkRuntimeEffect::Uniform" This reverts commit 0fdcaa5757a43b8b9c4fc9778c42592969dc8405. Reason for revert: Fix landed in Android Original change's description: > Revert "Remove (unused) gpuType from SkRuntimeEffect::Uniform" > > This reverts commit cc80a475662e573df8a4b625cd2a4f15ff4d31c2. > > Reason for revert: IWYU cleanup broke less IWYU-clean Android, > > frameworks/native/libs/renderengine/skia/filters/BlurFilter.cpp:180:17: error: variable has incomplete type 'SkRRect' > SkRRect roundedRect; > ^ > external/skia/include/core/SkCanvas.h:58:7: note: forward declaration of 'SkRRect' > class SkRRect; > > > Original change's description: > > Remove (unused) gpuType from SkRuntimeEffect::Uniform > > > > Also remove some unnecessary includes, then IWYU. > > > > Change-Id: I41e88f0e661c59e75cb26e28768801b811fe8ee8 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371140 > > Commit-Queue: Brian Osman <brianosman@google.com> > > Reviewed-by: John Stiles <johnstiles@google.com> > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > TBR=bsalomon@google.com,brianosman@google.com,johnstiles@google.com > > Change-Id: Id655a6835ebffdb4f5f82474c287c09a69a737df > No-Tree-Checks: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371941 > Reviewed-by: Mike Klein <mtklein@google.com> > Commit-Queue: Mike Klein <mtklein@google.com> # Not skipping CQ checks because this is a reland. Change-Id: I67deaee08f1dfea8d91121b3e665d2e6036b6139 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372216 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2021-02-18 20:51:20 +00:00
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
2021-03-23 21:04:41 +00:00
#include "include/core/SkShader.h"
#include "include/core/SkSpan.h"
#include "include/core/SkString.h"
#include "include/private/SkOnce.h"
#include "include/private/SkSLSampleUsage.h"
#include <vector>
Reland "Remove (unused) gpuType from SkRuntimeEffect::Uniform" This reverts commit 0fdcaa5757a43b8b9c4fc9778c42592969dc8405. Reason for revert: Fix landed in Android Original change's description: > Revert "Remove (unused) gpuType from SkRuntimeEffect::Uniform" > > This reverts commit cc80a475662e573df8a4b625cd2a4f15ff4d31c2. > > Reason for revert: IWYU cleanup broke less IWYU-clean Android, > > frameworks/native/libs/renderengine/skia/filters/BlurFilter.cpp:180:17: error: variable has incomplete type 'SkRRect' > SkRRect roundedRect; > ^ > external/skia/include/core/SkCanvas.h:58:7: note: forward declaration of 'SkRRect' > class SkRRect; > > > Original change's description: > > Remove (unused) gpuType from SkRuntimeEffect::Uniform > > > > Also remove some unnecessary includes, then IWYU. > > > > Change-Id: I41e88f0e661c59e75cb26e28768801b811fe8ee8 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371140 > > Commit-Queue: Brian Osman <brianosman@google.com> > > Reviewed-by: John Stiles <johnstiles@google.com> > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > TBR=bsalomon@google.com,brianosman@google.com,johnstiles@google.com > > Change-Id: Id655a6835ebffdb4f5f82474c287c09a69a737df > No-Tree-Checks: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371941 > Reviewed-by: Mike Klein <mtklein@google.com> > Commit-Queue: Mike Klein <mtklein@google.com> # Not skipping CQ checks because this is a reland. Change-Id: I67deaee08f1dfea8d91121b3e665d2e6036b6139 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372216 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2021-02-18 20:51:20 +00:00
class GrRecordingContext;
class SkBlender;
class SkFilterColorProgram;
Reland "Remove (unused) gpuType from SkRuntimeEffect::Uniform" This reverts commit 0fdcaa5757a43b8b9c4fc9778c42592969dc8405. Reason for revert: Fix landed in Android Original change's description: > Revert "Remove (unused) gpuType from SkRuntimeEffect::Uniform" > > This reverts commit cc80a475662e573df8a4b625cd2a4f15ff4d31c2. > > Reason for revert: IWYU cleanup broke less IWYU-clean Android, > > frameworks/native/libs/renderengine/skia/filters/BlurFilter.cpp:180:17: error: variable has incomplete type 'SkRRect' > SkRRect roundedRect; > ^ > external/skia/include/core/SkCanvas.h:58:7: note: forward declaration of 'SkRRect' > class SkRRect; > > > Original change's description: > > Remove (unused) gpuType from SkRuntimeEffect::Uniform > > > > Also remove some unnecessary includes, then IWYU. > > > > Change-Id: I41e88f0e661c59e75cb26e28768801b811fe8ee8 > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371140 > > Commit-Queue: Brian Osman <brianosman@google.com> > > Reviewed-by: John Stiles <johnstiles@google.com> > > Reviewed-by: Brian Salomon <bsalomon@google.com> > > TBR=bsalomon@google.com,brianosman@google.com,johnstiles@google.com > > Change-Id: Id655a6835ebffdb4f5f82474c287c09a69a737df > No-Tree-Checks: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/371941 > Reviewed-by: Mike Klein <mtklein@google.com> > Commit-Queue: Mike Klein <mtklein@google.com> # Not skipping CQ checks because this is a reland. Change-Id: I67deaee08f1dfea8d91121b3e665d2e6036b6139 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372216 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
2021-02-18 20:51:20 +00:00
class SkImage;
namespace SkSL {
class FunctionDefinition;
struct Program;
enum class ProgramKind : int8_t;
} // namespace SkSL
namespace skvm {
class Program;
} // namespace skvm
/*
* SkRuntimeEffect supports creating custom SkShader and SkColorFilter objects using Skia's SkSL
* shading language.
*
* NOTE: This API is experimental and subject to change.
*/
class SK_API SkRuntimeEffect : public SkRefCnt {
public:
// Reflected description of a uniform variable in the effect's SkSL
struct Uniform {
enum class Type {
kFloat,
kFloat2,
kFloat3,
kFloat4,
kFloat2x2,
kFloat3x3,
kFloat4x4,
kInt,
kInt2,
kInt3,
kInt4,
};
enum Flags {
kArray_Flag = 0x1,
kSRGBUnpremul_Flag = 0x2,
};
SkString name;
size_t offset;
Type type;
int count;
uint32_t flags;
bool isArray() const { return SkToBool(this->flags & kArray_Flag); }
size_t sizeInBytes() const;
};
// Reflected description of a uniform child (shader or colorFilter) in the effect's SkSL
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
struct Child {
enum class Type {
kShader,
kColorFilter,
};
SkString name;
Type type;
int index;
};
struct Options {
// For testing purposes, completely disable the inliner. (Normally, Runtime Effects don't
// run the inliner directly, but they still get an inlining pass once they are painted.)
bool forceNoInline = false;
// For testing purposes only; only honored when GR_TEST_UTILS is enabled. This flag lifts
// the ES2 restrictions on Runtime Effects that are gated by the `strictES2Mode` check.
// Be aware that the software renderer and pipeline-stage effect are still largely
// ES3-unaware and can still fail or crash if post-ES2 features are used.
bool enforceES2Restrictions = true;
};
// If the effect is compiled successfully, `effect` will be non-null.
// Otherwise, `errorText` will contain the reason for failure.
struct Result {
sk_sp<SkRuntimeEffect> effect;
SkString errorText;
};
// MakeForColorFilter and MakeForShader verify that the SkSL code is valid for those stages of
// the Skia pipeline. In all of the signatures described below, color parameters and return
// values are flexible. They are listed as being 'vec4', but they can also be 'half4' or
// 'float4'. ('vec4' is an alias for 'float4').
// Color filter SkSL requires an entry point that looks like:
// vec4 main(vec4 inColor) { ... }
static Result MakeForColorFilter(SkString sksl, const Options&);
// Shader SkSL requires an entry point that looks like:
// vec4 main(vec2 inCoords) { ... }
// -or-
// vec4 main(vec2 inCoords, vec4 inColor) { ... }
//
// Most shaders don't use the input color, so that parameter is optional.
static Result MakeForShader(SkString sksl, const Options&);
// Blend SkSL requires an entry point that looks like:
// vec4 main(vec4 srcColor, vec4 dstColor) { ... }
static Result MakeForBlender(SkString sksl, const Options&);
Reland "Remove deprecated form of SkRuntimeEffect::Make." This reverts commit e89b50ae054c08fc03ad5e7349d28c6a565e054b. Reason for revert: landed Android fix at http://ag/13544365 (master) and http://ag/13554983 (sc-dev) Original change's description: > Android roll broke with a compilation error: > frameworks/base/libs/hwui/jni/Shader.cpp:243:37: error: no matching function for call to 'get' > sk_sp<SkRuntimeEffect> effect = std::get<0>(result) > > Revert "Remove deprecated form of SkRuntimeEffect::Make." > > This reverts commit 1cda19436633c283561fe9a51f221ea9bf0ba2a3. > > Reason for revert: <INSERT REASONING HERE> > > Original change's description: > > Remove deprecated form of SkRuntimeEffect::Make. > > > > Chromium has migrated to the new API at https://crrev.com/c/2675855. > > > > Change-Id: Id4af77db2c462348e8031d28f56e543ad619c19c > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/367060 > > Reviewed-by: Brian Osman <brianosman@google.com> > > Commit-Queue: Brian Osman <brianosman@google.com> > > Commit-Queue: John Stiles <johnstiles@google.com> > > Auto-Submit: John Stiles <johnstiles@google.com> > > TBR=mtklein@google.com,brianosman@google.com,johnstiles@google.com > > Change-Id: Ie18f865f3b7f5b0263db1e52b19cf6faa0500fdd > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/368616 > Reviewed-by: Stan Iliev <stani@google.com> > Commit-Queue: Stan Iliev <stani@google.com> TBR=mtklein@google.com,brianosman@google.com,stani@google.com,johnstiles@google.com Change-Id: I9d679013cb275dc80aaaa977b7f1f4da31f36d1e No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/c/skia/+/369037 Reviewed-by: John Stiles <johnstiles@google.com> Reviewed-by: Derek Sollenberger <djsollen@google.com> Commit-Queue: John Stiles <johnstiles@google.com>
2021-02-11 22:40:03 +00:00
// We can't use a default argument for `options` due to a bug in Clang.
// https://bugs.llvm.org/show_bug.cgi?id=36684
static Result MakeForColorFilter(SkString sksl) {
return MakeForColorFilter(std::move(sksl), Options{});
}
static Result MakeForShader(SkString sksl) {
return MakeForShader(std::move(sksl), Options{});
}
static Result MakeForBlender(SkString sksl) {
return MakeForBlender(std::move(sksl), Options{});
}
static Result MakeForColorFilter(std::unique_ptr<SkSL::Program> program);
static Result MakeForShader(std::unique_ptr<SkSL::Program> program);
static Result MakeForBlender(std::unique_ptr<SkSL::Program> program);
// Object that allows passing either an SkShader or SkColorFilter as a child
struct ChildPtr {
ChildPtr(sk_sp<SkShader> s) : shader(std::move(s)) {}
ChildPtr(sk_sp<SkColorFilter> cf) : colorFilter(std::move(cf)) {}
sk_sp<SkShader> shader;
sk_sp<SkColorFilter> colorFilter;
};
sk_sp<SkShader> makeShader(sk_sp<SkData> uniforms,
sk_sp<SkShader> children[],
size_t childCount,
const SkMatrix* localMatrix,
2021-03-23 21:04:41 +00:00
bool isOpaque) const;
sk_sp<SkShader> makeShader(sk_sp<SkData> uniforms,
SkSpan<ChildPtr> children,
const SkMatrix* localMatrix,
bool isOpaque) const;
sk_sp<SkImage> makeImage(GrRecordingContext*,
sk_sp<SkData> uniforms,
sk_sp<SkShader> children[],
size_t childCount,
const SkMatrix* localMatrix,
SkImageInfo resultInfo,
2021-03-23 21:04:41 +00:00
bool mipmapped) const;
2021-03-23 21:04:41 +00:00
sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> uniforms) const;
sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> uniforms,
sk_sp<SkColorFilter> children[],
2021-03-23 21:04:41 +00:00
size_t childCount) const;
sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> uniforms,
SkSpan<ChildPtr> children) const;
sk_sp<SkBlender> makeBlender(sk_sp<SkData> uniforms) const;
const SkString& source() const { return fSkSL; }
template <typename T>
class ConstIterable {
public:
ConstIterable(const std::vector<T>& vec) : fVec(vec) {}
using const_iterator = typename std::vector<T>::const_iterator;
const_iterator begin() const { return fVec.begin(); }
const_iterator end() const { return fVec.end(); }
size_t count() const { return fVec.size(); }
private:
const std::vector<T>& fVec;
};
// Combined size of all 'uniform' variables. When calling makeColorFilter or makeShader,
// provide an SkData of this size, containing values for all of those variables.
size_t uniformSize() const;
ConstIterable<Uniform> uniforms() const { return ConstIterable<Uniform>(fUniforms); }
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
ConstIterable<Child> children() const { return ConstIterable<Child>(fChildren); }
// Returns pointer to the named uniform variable's description, or nullptr if not found
const Uniform* findUniform(const char* name) const;
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
// Returns pointer to the named child's description, or nullptr if not found
const Child* findChild(const char* name) const;
static void RegisterFlattenables();
~SkRuntimeEffect() override;
private:
enum Flags {
kUsesSampleCoords_Flag = 0x1,
kAllowColorFilter_Flag = 0x2,
kAllowShader_Flag = 0x4,
kAllowBlender_Flag = 0x8,
};
SkRuntimeEffect(SkString sksl,
std::unique_ptr<SkSL::Program> baseProgram,
const Options& options,
const SkSL::FunctionDefinition& main,
std::vector<Uniform>&& uniforms,
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
std::vector<Child>&& children,
std::vector<SkSL::SampleUsage>&& sampleUsages,
uint32_t flags);
static Result Make(std::unique_ptr<SkSL::Program> program, SkSL::ProgramKind kind);
static Result Make(SkString sksl, const Options& options, SkSL::ProgramKind kind);
static Result Make(SkString sksl, std::unique_ptr<SkSL::Program> program,
const Options& options, SkSL::ProgramKind kind);
uint32_t hash() const { return fHash; }
bool usesSampleCoords() const { return (fFlags & kUsesSampleCoords_Flag); }
bool allowShader() const { return (fFlags & kAllowShader_Flag); }
bool allowColorFilter() const { return (fFlags & kAllowColorFilter_Flag); }
bool allowBlender() const { return (fFlags & kAllowBlender_Flag); }
const SkFilterColorProgram* getFilterColorProgram();
#if SK_SUPPORT_GPU
friend class GrSkSLFP; // fBaseProgram, fSampleUsages
friend class GrGLSLSkSLFP; //
#endif
friend class SkRTShader; // fBaseProgram, fMain
friend class SkRuntimeColorFilter; //
friend class SkFilterColorProgram;
uint32_t fHash;
SkString fSkSL;
std::unique_ptr<SkSL::Program> fBaseProgram;
const SkSL::FunctionDefinition& fMain;
std::vector<Uniform> fUniforms;
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
std::vector<Child> fChildren;
std::vector<SkSL::SampleUsage> fSampleUsages;
std::unique_ptr<SkFilterColorProgram> fFilterColorProgram;
uint32_t fFlags; // Flags
};
2021-03-23 21:04:41 +00:00
/** Base class for SkRuntimeShaderBuilder, defined below. */
template <typename Child> class SkRuntimeEffectBuilder {
public:
struct BuilderUniform {
// Copy 'val' to this variable. No type conversion is performed - 'val' must be same
// size as expected by the effect. Information about the variable can be queried by
// looking at fVar. If the size is incorrect, no copy will be performed, and debug
// builds will abort. If this is the result of querying a missing variable, fVar will
// be nullptr, and assigning will also do nothing (and abort in debug builds).
template <typename T>
std::enable_if_t<std::is_trivially_copyable<T>::value, BuilderUniform&> operator=(
const T& val) {
if (!fVar) {
SkDEBUGFAIL("Assigning to missing variable");
} else if (sizeof(val) != fVar->sizeInBytes()) {
SkDEBUGFAIL("Incorrect value size");
} else {
memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
&val, sizeof(val));
}
return *this;
}
BuilderUniform& operator=(const SkMatrix& val) {
if (!fVar) {
SkDEBUGFAIL("Assigning to missing variable");
} else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
SkDEBUGFAIL("Incorrect value size");
} else {
float* data = SkTAddOffset<float>(fOwner->writableUniformData(), fVar->offset);
data[0] = val.get(0); data[1] = val.get(3); data[2] = val.get(6);
data[3] = val.get(1); data[4] = val.get(4); data[5] = val.get(7);
data[6] = val.get(2); data[7] = val.get(5); data[8] = val.get(8);
}
return *this;
}
template <typename T>
bool set(const T val[], const int count) {
static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
if (!fVar) {
SkDEBUGFAIL("Assigning to missing variable");
return false;
} else if (sizeof(T) * count != fVar->sizeInBytes()) {
SkDEBUGFAIL("Incorrect value size");
return false;
} else {
memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
val, sizeof(T) * count);
}
return true;
}
2021-03-23 21:04:41 +00:00
SkRuntimeEffectBuilder* fOwner;
const SkRuntimeEffect::Uniform* fVar; // nullptr if the variable was not found
};
struct BuilderChild {
2021-03-23 21:04:41 +00:00
template <typename C> BuilderChild& operator=(C&& val) {
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
// TODO(skbug:11813): Validate that the type of val lines up with the type of the child
// (SkShader vs. SkColorFilter).
if (!fChild) {
2021-03-23 21:04:41 +00:00
SkDEBUGFAIL("Assigning to missing child");
} else {
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
fOwner->fChildren[fChild->index] = std::forward<C>(val);
2021-03-23 21:04:41 +00:00
}
return *this;
}
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
SkRuntimeEffectBuilder* fOwner;
const SkRuntimeEffect::Child* fChild; // nullptr if the child was not found
// DEPRECATED - Left temporarily for Android
int fIndex; // -1 if the child was not found
};
const SkRuntimeEffect* effect() const { return fEffect.get(); }
BuilderUniform uniform(const char* name) { return { this, fEffect->findUniform(name) }; }
Reland "Better first-class shader & color filter support in runtime effects" This is a reland of adadb95a9f1ef21ccc5264c7d0bdc83b56cf91e9 ... adds a temporary workaround for some Android framework code. Original change's description: > Better first-class shader & color filter support in runtime effects > > This does a few things, because they're all intertwined: > > 1) SkRuntimeEffect's API now includes details about children (which Skia > stage was declared, not just the name). The factories verify that the > declared types in the SkSL match up with the C++ types being passed. > Today, we still only support adding children of the same type, so the > checks are simple. Once we allow mixing types, we'll be testing the > declared type against the actual C++ type supplied for each slot. > 2) Adds sample variants that supply the input color to the child. This > is now the only way to invoke a colorFilter child. Internally, we > support passing a color when invoking a child shader, but I'm not > exposing that. It's not clearly part of the semantics of the Skia > pipeline, and is almost never useful. It also exposes users to > several inconsistencies (skbug.com/11942). > 3) Because of #2, it's possible that we can't compute a reusable program > to filter individual colors. In that case, we don't set the constant > output for constant input optimization, and filterColor4f falls back > to the slower base-class implementation. > > Bug: skia:11813 skia:11942 > Change-Id: I06c41e1b35056e486f3163a72acf6b9535d7fed4 > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/401917 > Commit-Queue: Brian Osman <brianosman@google.com> > Reviewed-by: Mike Klein <mtklein@google.com> Bug: skia:11813 skia:11942 Change-Id: I2c31b147ed86fa8c4dddefb7066bc1d07fe0d285 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/404637 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
2021-04-21 13:57:19 +00:00
BuilderChild child(const char* name) {
const SkRuntimeEffect::Child* child = fEffect->findChild(name);
return { this, child, child ? child->index : -1 };
}
2021-03-23 21:04:41 +00:00
protected:
SkRuntimeEffectBuilder() = delete;
explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect)
: fEffect(std::move(effect))
, fUniforms(SkData::MakeUninitialized(fEffect->uniformSize()))
, fChildren(fEffect->children().count()) {}
SkRuntimeEffectBuilder(SkRuntimeEffectBuilder&&) = default;
SkRuntimeEffectBuilder(const SkRuntimeEffectBuilder&) = default;
SkRuntimeEffectBuilder& operator=(SkRuntimeEffectBuilder&&) = delete;
SkRuntimeEffectBuilder& operator=(const SkRuntimeEffectBuilder&) = delete;
sk_sp<SkData> uniforms() { return fUniforms; }
Child* children() { return fChildren.data(); }
size_t numChildren() { return fChildren.size(); }
private:
void* writableUniformData() {
if (!fUniforms->unique()) {
fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
}
return fUniforms->writable_data();
}
sk_sp<SkRuntimeEffect> fEffect;
sk_sp<SkData> fUniforms;
std::vector<Child> fChildren;
};
/**
* SkRuntimeShaderBuilder is a utility to simplify creating SkShader objects from SkRuntimeEffects.
*
* NOTE: Like SkRuntimeEffect, this API is experimental and subject to change!
*
* Given an SkRuntimeEffect, the SkRuntimeShaderBuilder manages creating an input data block and
* provides named access to the 'uniform' variables in that block, as well as named access
* to a list of child shader slots. Usage:
*
* sk_sp<SkRuntimeEffect> effect = ...;
* SkRuntimeShaderBuilder builder(effect);
* builder.uniform("some_uniform_float") = 3.14f;
* builder.uniform("some_uniform_matrix") = SkM44::Rotate(...);
* builder.child("some_child_effect") = mySkImage->makeShader(...);
* ...
* sk_sp<SkShader> shader = builder.makeShader(nullptr, false);
*
* Note that SkRuntimeShaderBuilder is built entirely on the public API of SkRuntimeEffect,
* so can be used as-is or serve as inspiration for other interfaces or binding techniques.
*/
class SK_API SkRuntimeShaderBuilder : public SkRuntimeEffectBuilder<sk_sp<SkShader>> {
public:
explicit SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect>);
// This is currently required by Android Framework but may go away if that dependency
// can be removed.
SkRuntimeShaderBuilder(const SkRuntimeShaderBuilder&) = default;
~SkRuntimeShaderBuilder();
sk_sp<SkShader> makeShader(const SkMatrix* localMatrix, bool isOpaque);
sk_sp<SkImage> makeImage(GrRecordingContext*,
const SkMatrix* localMatrix,
SkImageInfo resultInfo,
bool mipmapped);
private:
2021-03-23 21:04:41 +00:00
using INHERITED = SkRuntimeEffectBuilder<sk_sp<SkShader>>;
};
#endif