Convert GrDitherEffect to a runtime FP
Includes a change so that we can create non-ES2 runtime effects, even outside of tests/tools. It's still locked to a private API, so clients can't access the functionality. Change-Id: Ie0643da2071bd223fccf05b35f3a7b6f7bbc4876 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/423578 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
a8d2bf7b29
commit
2fa843abc2
@ -309,8 +309,6 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/effects/GrTextureEffect.h",
|
||||
"$_src/gpu/effects/GrYUVtoRGBEffect.cpp",
|
||||
"$_src/gpu/effects/GrYUVtoRGBEffect.h",
|
||||
"$_src/gpu/effects/generated/GrDitherEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrDitherEffect.h",
|
||||
"$_src/gpu/geometry/GrPathUtils.cpp",
|
||||
"$_src/gpu/geometry/GrPathUtils.h",
|
||||
"$_src/gpu/geometry/GrQuad.cpp",
|
||||
|
@ -207,7 +207,5 @@ skia_sksl_gpu_sources = [
|
||||
"$_src/sksl/codegen/SkSLSPIRVtoHLSL.h",
|
||||
]
|
||||
|
||||
skia_gpu_processor_sources = [
|
||||
"$_src/gpu/effects/GrDitherEffect.fp",
|
||||
"$_src/gpu/gradients/GrUnrolledBinaryGradientColorizer.fp",
|
||||
]
|
||||
skia_gpu_processor_sources =
|
||||
[ "$_src/gpu/gradients/GrUnrolledBinaryGradientColorizer.fp" ]
|
||||
|
@ -87,14 +87,20 @@ public:
|
||||
int index;
|
||||
};
|
||||
|
||||
struct Options {
|
||||
class Options {
|
||||
public:
|
||||
// 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.
|
||||
|
||||
private:
|
||||
friend class SkRuntimeEffect;
|
||||
friend class SkRuntimeEffectPriv;
|
||||
|
||||
// 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.
|
||||
// This is only intended for use by tests and certain internally created effects.
|
||||
bool enforceES2Restrictions = true;
|
||||
};
|
||||
|
||||
|
@ -149,9 +149,7 @@ SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl, const Options& opti
|
||||
SkSL::Program::Settings settings;
|
||||
settings.fInlineThreshold = 0;
|
||||
settings.fForceNoInline = options.forceNoInline;
|
||||
#if GR_TEST_UTILS
|
||||
settings.fEnforceES2Restrictions = options.enforceES2Restrictions;
|
||||
#endif
|
||||
settings.fAllowNarrowingConversions = true;
|
||||
program = compiler->convertProgram(kind, SkSL::String(sksl.c_str(), sksl.size()), settings);
|
||||
|
||||
@ -174,10 +172,6 @@ SkRuntimeEffect::Result SkRuntimeEffect::Make(std::unique_ptr<SkSL::Program> pro
|
||||
const Options& options,
|
||||
SkSL::ProgramKind kind) {
|
||||
SkSL::SharedCompiler compiler;
|
||||
SkSL::Program::Settings settings;
|
||||
settings.fInlineThreshold = 0;
|
||||
settings.fForceNoInline = options.forceNoInline;
|
||||
settings.fAllowNarrowingConversions = true;
|
||||
|
||||
// Find 'main', then locate the sample coords parameter. (It might not be present.)
|
||||
const SkSL::FunctionDefinition* main = SkSL::Program_GetFunction(*program, "main");
|
||||
|
@ -32,9 +32,11 @@ inline sk_sp<SkRuntimeEffect> SkMakeCachedRuntimeEffect(SkRuntimeEffect::Result
|
||||
|
||||
// Internal API that assumes (and asserts) that the shader code is valid, but does no internal
|
||||
// caching. Used when the caller will cache the result in a static variable.
|
||||
inline sk_sp<SkRuntimeEffect> SkMakeRuntimeEffect(SkRuntimeEffect::Result (*make)(SkString sksl),
|
||||
const char* sksl) {
|
||||
auto result = make(SkString{sksl});
|
||||
inline sk_sp<SkRuntimeEffect> SkMakeRuntimeEffect(
|
||||
SkRuntimeEffect::Result (*make)(SkString, const SkRuntimeEffect::Options&),
|
||||
const char* sksl,
|
||||
SkRuntimeEffect::Options options = SkRuntimeEffect::Options{}) {
|
||||
auto result = make(SkString{sksl}, options);
|
||||
SkASSERTF(result.effect, "%s", result.errorText.c_str());
|
||||
return result.effect;
|
||||
}
|
||||
@ -126,6 +128,12 @@ public:
|
||||
static bool SupportsConstantOutputForConstantInput(sk_sp<SkRuntimeEffect> effect) {
|
||||
return effect->getFilterColorProgram();
|
||||
}
|
||||
|
||||
static SkRuntimeEffect::Options ES3Options() {
|
||||
SkRuntimeEffect::Options options;
|
||||
options.enforceES2Restrictions = false;
|
||||
return options;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -63,7 +63,6 @@ public:
|
||||
kGrDistanceFieldA8TextGeoProc_ClassID,
|
||||
kGrDistanceFieldLCDTextGeoProc_ClassID,
|
||||
kGrDistanceFieldPathGeoProc_ClassID,
|
||||
kGrDitherEffect_ClassID,
|
||||
kGrDSLFPTest_DoStatement_ClassID,
|
||||
kGrDSLFPTest_ForStatement_ClassID,
|
||||
kGrDSLFPTest_IfStatement_ClassID,
|
||||
|
@ -146,7 +146,7 @@ SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories()
|
||||
* we verify the count is as expected. If a new factory is added, then these numbers must be
|
||||
* manually adjusted.
|
||||
*/
|
||||
static constexpr int kFPFactoryCount = 17;
|
||||
static constexpr int kFPFactoryCount = 16;
|
||||
static constexpr int kGPFactoryCount = 14;
|
||||
static constexpr int kXPFactoryCount = 4;
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "src/core/SkMipmap.h"
|
||||
#include "src/core/SkPaintPriv.h"
|
||||
#include "src/core/SkResourceCache.h"
|
||||
#include "src/core/SkRuntimeEffectPriv.h"
|
||||
#include "src/core/SkTraceEvent.h"
|
||||
#include "src/gpu/GrCaps.h"
|
||||
#include "src/gpu/GrColorInfo.h"
|
||||
@ -42,7 +43,7 @@
|
||||
#include "src/gpu/effects/GrBicubicEffect.h"
|
||||
#include "src/gpu/effects/GrBlendFragmentProcessor.h"
|
||||
#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
|
||||
#include "src/gpu/effects/generated/GrDitherEffect.h"
|
||||
#include "src/gpu/effects/GrSkSLFP.h"
|
||||
#include "src/image/SkImage_Base.h"
|
||||
#include "src/shaders/SkShaderBase.h"
|
||||
|
||||
@ -322,6 +323,67 @@ static inline float dither_range_for_config(GrColorType dstColorType) {
|
||||
}
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
static std::unique_ptr<GrFragmentProcessor> make_dither_effect(
|
||||
std::unique_ptr<GrFragmentProcessor> inputFP, float range, const GrShaderCaps* caps) {
|
||||
if (range == 0 || inputFP == nullptr) {
|
||||
return inputFP;
|
||||
}
|
||||
|
||||
if (caps->integerSupport()) {
|
||||
// This ordered-dither code is lifted from the cpu backend.
|
||||
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
|
||||
uniform half range;
|
||||
half4 main(float2 xy, half4 color) {
|
||||
uint x = uint(sk_FragCoord.x);
|
||||
uint y = uint(sk_FragCoord.y) ^ x;
|
||||
uint m = (y & 1) << 5 | (x & 1) << 4 |
|
||||
(y & 2) << 2 | (x & 2) << 1 |
|
||||
(y & 4) >> 1 | (x & 4) >> 2;
|
||||
half value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
|
||||
|
||||
// For each color channel, add the random offset to the channel value and then clamp
|
||||
// between 0 and alpha to keep the color premultiplied.
|
||||
return half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
|
||||
}
|
||||
)", SkRuntimeEffectPriv::ES3Options());
|
||||
return GrSkSLFP::Make(effect, "Dither", std::move(inputFP),
|
||||
GrSkSLFP::OptFlags::kPreservesOpaqueInput,
|
||||
"range", range);
|
||||
} else {
|
||||
// Simulate the integer effect used above using step/mod/abs. For speed, simulates a 4x4
|
||||
// dither pattern rather than an 8x8 one. Since it's 4x4, this is effectively computing:
|
||||
// uint m = (y & 1) << 3 | (x & 1) << 2 |
|
||||
// (y & 2) << 0 | (x & 2) >> 1;
|
||||
// where 'y' has already been XOR'ed with 'x' as in the integer-supported case.
|
||||
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
|
||||
uniform half range;
|
||||
half4 main(float2 xy, half4 color) {
|
||||
// To get the low bit of p.xy, we compute mod 2.0; for the high bit, we mod 4.0
|
||||
half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0));
|
||||
// Use step to convert the 0-3 value in bits.zw into a 0|1 value. bits.xy is
|
||||
// already 0|1.
|
||||
bits.zw = step(2.0, bits.zw);
|
||||
// bits was constructed such that the p.x bits were already in the right place for
|
||||
// interleaving (in bits.yw). We just need to update the other bits from p.y to
|
||||
// (p.x ^ p.y). These are in bits.xz. Since the values are 0|1, we can simulate ^ as
|
||||
// abs(y - x).
|
||||
bits.xz = abs(bits.xz - bits.yw);
|
||||
|
||||
// Manual binary sum, divide by N^2, and offset
|
||||
value = dot(bits, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0))
|
||||
- 15.0 / 32.0;
|
||||
|
||||
// For each color channel, add the random offset to the channel value and then clamp
|
||||
// between 0 and alpha to keep the color premultiplied.
|
||||
return half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
|
||||
}
|
||||
)");
|
||||
return GrSkSLFP::Make(effect, "Dither", std::move(inputFP),
|
||||
GrSkSLFP::OptFlags::kPreservesOpaqueInput,
|
||||
"range", range);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
|
||||
@ -435,7 +497,8 @@ static inline bool skpaint_to_grpaint_impl(GrRecordingContext* context,
|
||||
GrColorType ct = dstColorInfo.colorType();
|
||||
if (SkPaintPriv::ShouldDither(skPaint, GrColorTypeToSkColorType(ct)) && paintFP != nullptr) {
|
||||
float ditherRange = dither_range_for_config(ct);
|
||||
paintFP = GrDitherEffect::Make(std::move(paintFP), ditherRange);
|
||||
paintFP = make_dither_effect(
|
||||
std::move(paintFP), ditherRange, context->priv().caps()->shaderCaps());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
in fragmentProcessor inputFP;
|
||||
|
||||
// Larger values increase the strength of the dithering effect.
|
||||
in uniform half range;
|
||||
|
||||
half4 main() {
|
||||
half4 color = sample(inputFP);
|
||||
half value;
|
||||
@if (sk_Caps.integerSupport)
|
||||
{
|
||||
// This ordered-dither code is lifted from the cpu backend.
|
||||
uint x = uint(sk_FragCoord.x);
|
||||
uint y = uint(sk_FragCoord.y) ^ x;
|
||||
uint m = (y & 1) << 5 | (x & 1) << 4 |
|
||||
(y & 2) << 2 | (x & 2) << 1 |
|
||||
(y & 4) >> 1 | (x & 4) >> 2;
|
||||
value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
|
||||
} else {
|
||||
// Simulate the integer effect used above using step/mod/abs. For speed, simulates a 4x4
|
||||
// dither pattern rather than an 8x8 one. Since it's 4x4, this is effectively computing:
|
||||
// uint m = (y & 1) << 3 | (x & 1) << 2 |
|
||||
// (y & 2) << 0 | (x & 2) >> 1;
|
||||
// where 'y' has already been XOR'ed with 'x' as in the integer-supported case.
|
||||
|
||||
// To get the low bit of p.x and p.y, we compute mod 2.0; for the high bit, we mod 4.0
|
||||
half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0));
|
||||
// Use step to convert the 0-3 value in bits.zw into a 0|1 value. bits.xy is already 0|1.
|
||||
bits.zw = step(2.0, bits.zw);
|
||||
// bits was constructed such that the p.x bits were already in the right place for
|
||||
// interleaving (in bits.yw). We just need to update the other bits from p.y to (p.x ^ p.y).
|
||||
// These are in bits.xz. Since the values are 0|1, we can simulate ^ as abs(y - x).
|
||||
bits.xz = abs(bits.xz - bits.yw);
|
||||
|
||||
// Manual binary sum, divide by N^2, and offset
|
||||
value = dot(bits, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
|
||||
}
|
||||
// For each color channel, add the random offset to the channel value and then clamp
|
||||
// between 0 and alpha to keep the color premultiplied.
|
||||
return half4(clamp(color.rgb + value * range, 0.0, color.a), color.a);
|
||||
}
|
||||
|
||||
@optimizationFlags {
|
||||
ProcessorOptimizationFlags(inputFP.get()) & kPreservesOpaqueInput_OptimizationFlag
|
||||
}
|
||||
|
||||
@test(d) {
|
||||
float range = 1.0f - d->fRandom->nextRangeF(0.0f, 1.0f);
|
||||
return GrDitherEffect::Make(GrProcessorUnitTest::MakeChildFP(d), range);
|
||||
}
|
||||
|
||||
@make {
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
float range) {
|
||||
if (range == 0.0 || inputFP == nullptr) {
|
||||
return inputFP;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(std::move(inputFP), range));
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**************************************************************************************************
|
||||
*** This file was autogenerated from GrDitherEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#include "GrDitherEffect.h"
|
||||
|
||||
#include "src/core/SkUtils.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 GrGLSLDitherEffect : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLDitherEffect() {}
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>();
|
||||
(void)_outer;
|
||||
auto range = _outer.range;
|
||||
(void)range;
|
||||
rangeVar = args.fUniformHandler->addUniform(
|
||||
&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "range");
|
||||
SkString _sample0 = this->invokeChild(0, args);
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(half4 color = %s;
|
||||
half value;
|
||||
@if (sk_Caps.integerSupport) {
|
||||
uint x = uint(sk_FragCoord.x);
|
||||
uint y = uint(sk_FragCoord.y) ^ x;
|
||||
uint m = (((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) >> 1) | (x & 4) >> 2;
|
||||
value = half(m) / 64.0 - 0.4921875;
|
||||
} else {
|
||||
half4 bits = mod(half4(sk_FragCoord.yxyx), half4(2.0, 2.0, 4.0, 4.0));
|
||||
bits.zw = step(2.0, bits.zw);
|
||||
bits.xz = abs(bits.xz - bits.yw);
|
||||
value = dot(bits, half4(0.5, 0.25, 0.125, 0.0625)) - 0.46875;
|
||||
}
|
||||
return half4(clamp(color.xyz + value * %s, 0.0, color.w), color.w);
|
||||
)SkSL",
|
||||
_sample0.c_str(),
|
||||
args.fUniformHandler->getUniformCStr(rangeVar));
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {
|
||||
const GrDitherEffect& _outer = _proc.cast<GrDitherEffect>();
|
||||
{ pdman.set1f(rangeVar, _outer.range); }
|
||||
}
|
||||
UniformHandle rangeVar;
|
||||
};
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> GrDitherEffect::onMakeProgramImpl() const {
|
||||
return std::make_unique<GrGLSLDitherEffect>();
|
||||
}
|
||||
void GrDitherEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {}
|
||||
bool GrDitherEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrDitherEffect& that = other.cast<GrDitherEffect>();
|
||||
(void)that;
|
||||
if (range != that.range) return false;
|
||||
return true;
|
||||
}
|
||||
GrDitherEffect::GrDitherEffect(const GrDitherEffect& src)
|
||||
: INHERITED(kGrDitherEffect_ClassID, src.optimizationFlags()), range(src.range) {
|
||||
this->cloneAndRegisterAllChildProcessors(src);
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrDitherEffect::clone() const {
|
||||
return std::make_unique<GrDitherEffect>(*this);
|
||||
}
|
||||
#if GR_TEST_UTILS
|
||||
SkString GrDitherEffect::onDumpInfo() const { return SkStringPrintf("(range=%f)", range); }
|
||||
#endif
|
||||
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDitherEffect);
|
||||
#if GR_TEST_UTILS
|
||||
std::unique_ptr<GrFragmentProcessor> GrDitherEffect::TestCreate(GrProcessorTestData* d) {
|
||||
float range = 1.0f - d->fRandom->nextRangeF(0.0f, 1.0f);
|
||||
return GrDitherEffect::Make(GrProcessorUnitTest::MakeChildFP(d), range);
|
||||
}
|
||||
#endif
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**************************************************************************************************
|
||||
*** This file was autogenerated from GrDitherEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#ifndef GrDitherEffect_DEFINED
|
||||
#define GrDitherEffect_DEFINED
|
||||
|
||||
#include "include/core/SkM44.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
|
||||
class GrDitherEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
float range) {
|
||||
if (range == 0.0 || inputFP == nullptr) {
|
||||
return inputFP;
|
||||
}
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(std::move(inputFP), range));
|
||||
}
|
||||
GrDitherEffect(const GrDitherEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "DitherEffect"; }
|
||||
float range;
|
||||
|
||||
private:
|
||||
GrDitherEffect(std::unique_ptr<GrFragmentProcessor> inputFP, float range)
|
||||
: INHERITED(kGrDitherEffect_ClassID,
|
||||
(OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
|
||||
kPreservesOpaqueInput_OptimizationFlag)
|
||||
, range(range) {
|
||||
this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
|
||||
}
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
#if GR_TEST_UTILS
|
||||
SkString onDumpInfo() const override;
|
||||
#endif
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
using INHERITED = GrFragmentProcessor;
|
||||
};
|
||||
#endif
|
@ -79,8 +79,7 @@ DEF_TEST(SkRuntimeEffectInvalid_SkCapsDisallowed, r) {
|
||||
|
||||
DEF_TEST(SkRuntimeEffectCanDisableES2Restrictions, r) {
|
||||
auto test_valid_es3 = [](skiatest::Reporter* r, const char* sksl) {
|
||||
SkRuntimeEffect::Options opt;
|
||||
opt.enforceES2Restrictions = false;
|
||||
SkRuntimeEffect::Options opt = SkRuntimeEffectPriv::ES3Options();
|
||||
auto [effect, errorText] = SkRuntimeEffect::MakeForShader(SkString(sksl), opt);
|
||||
REPORTER_ASSERT(r, effect, "%s", errorText.c_str());
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
#include "include/private/SkSLDefines.h" // for kDefaultInlineThreshold
|
||||
#include "include/utils/SkRandom.h"
|
||||
#include "src/core/SkRuntimeEffectPriv.h"
|
||||
#include "src/gpu/GrCaps.h"
|
||||
#include "src/gpu/GrDirectContextPriv.h"
|
||||
#include "tests/Test.h"
|
||||
@ -98,8 +99,8 @@ static void test_permutations(skiatest::Reporter* r,
|
||||
SkSurface* surface,
|
||||
const char* testFile,
|
||||
bool worksInES2) {
|
||||
SkRuntimeEffect::Options options;
|
||||
options.enforceES2Restrictions = worksInES2;
|
||||
SkRuntimeEffect::Options options =
|
||||
worksInES2 ? SkRuntimeEffect::Options{} : SkRuntimeEffectPriv::ES3Options();
|
||||
options.forceNoInline = false;
|
||||
test_one_permutation(r, surface, testFile, "", options);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user