1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef GrSkSLFP_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define GrSkSLFP_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkRuntimeEffect.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMacros.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkSpan_impl.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkVx.h" // IWYU pragma: keep 19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrFragmentProcessor.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorUnitTest.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h" 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 24*c8dee2aaSAndroid Build Coastguard Worker #include <cstring> 25*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 26*c8dee2aaSAndroid Build Coastguard Worker #include <string> 27*c8dee2aaSAndroid Build Coastguard Worker #include <string_view> 28*c8dee2aaSAndroid Build Coastguard Worker #include <utility> 29*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Worker class SkColorSpace; 32*c8dee2aaSAndroid Build Coastguard Worker class SkData; 33*c8dee2aaSAndroid Build Coastguard Worker class SkM44; 34*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu { class KeyBuilder; } 35*c8dee2aaSAndroid Build Coastguard Worker struct GrShaderCaps; 36*c8dee2aaSAndroid Build Coastguard Worker struct SkISize; 37*c8dee2aaSAndroid Build Coastguard Worker struct SkRect; 38*c8dee2aaSAndroid Build Coastguard Worker struct SkV2; 39*c8dee2aaSAndroid Build Coastguard Worker struct SkV4; 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker template <typename T> struct GrFPUniformType; 42*c8dee2aaSAndroid Build Coastguard Worker 43*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG 44*c8dee2aaSAndroid Build Coastguard Worker // UNIFORM_TYPE allows C++ types to be mapped onto SkRuntimeEffect::Uniform::Type 45*c8dee2aaSAndroid Build Coastguard Worker template <typename T> struct GrFPUniformType { 46*c8dee2aaSAndroid Build Coastguard Worker template <typename U> struct add_a_UNIFORM_TYPE_specialization_for {}; 47*c8dee2aaSAndroid Build Coastguard Worker static constexpr add_a_UNIFORM_TYPE_specialization_for<T> value = {}; 48*c8dee2aaSAndroid Build Coastguard Worker }; 49*c8dee2aaSAndroid Build Coastguard Worker #define UNIFORM_TYPE(E, ...) \ 50*c8dee2aaSAndroid Build Coastguard Worker template <> struct GrFPUniformType<__VA_ARGS__> { \ 51*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkRuntimeEffect::Uniform::Type value = SkRuntimeEffect::Uniform::Type::E; \ 52*c8dee2aaSAndroid Build Coastguard Worker }; \ 53*c8dee2aaSAndroid Build Coastguard Worker template <> struct GrFPUniformType<SkSpan<__VA_ARGS__>> { \ 54*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkRuntimeEffect::Uniform::Type value = SkRuntimeEffect::Uniform::Type::E; \ 55*c8dee2aaSAndroid Build Coastguard Worker } 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kFloat, float); 58*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kFloat2, SkV2); 59*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kFloat4, SkPMColor4f); 60*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kFloat4, SkRect); 61*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kFloat4, SkV4); 62*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kFloat4, skvx::Vec<4, float>); 63*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kFloat4x4, SkM44); 64*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kInt, int); 65*c8dee2aaSAndroid Build Coastguard Worker UNIFORM_TYPE(kInt2, SkISize); 66*c8dee2aaSAndroid Build Coastguard Worker 67*c8dee2aaSAndroid Build Coastguard Worker #undef UNIFORM_TYPE 68*c8dee2aaSAndroid Build Coastguard Worker #endif 69*c8dee2aaSAndroid Build Coastguard Worker 70*c8dee2aaSAndroid Build Coastguard Worker class GrSkSLFP : public GrFragmentProcessor { 71*c8dee2aaSAndroid Build Coastguard Worker public: 72*c8dee2aaSAndroid Build Coastguard Worker template <typename T> struct GrSpecializedUniform { 73*c8dee2aaSAndroid Build Coastguard Worker bool specialize; 74*c8dee2aaSAndroid Build Coastguard Worker T value; 75*c8dee2aaSAndroid Build Coastguard Worker }; 76*c8dee2aaSAndroid Build Coastguard Worker template <typename T> Specialize(const T & value)77*c8dee2aaSAndroid Build Coastguard Worker static GrSpecializedUniform<T> Specialize(const T& value) { 78*c8dee2aaSAndroid Build Coastguard Worker return {true, value}; 79*c8dee2aaSAndroid Build Coastguard Worker } 80*c8dee2aaSAndroid Build Coastguard Worker template <typename T> SpecializeIf(bool condition,const T & value)81*c8dee2aaSAndroid Build Coastguard Worker static GrSpecializedUniform<T> SpecializeIf(bool condition, const T& value) { 82*c8dee2aaSAndroid Build Coastguard Worker return {condition, value}; 83*c8dee2aaSAndroid Build Coastguard Worker } 84*c8dee2aaSAndroid Build Coastguard Worker 85*c8dee2aaSAndroid Build Coastguard Worker template <typename T> struct GrOptionalUniform { 86*c8dee2aaSAndroid Build Coastguard Worker bool enabled; 87*c8dee2aaSAndroid Build Coastguard Worker T value; 88*c8dee2aaSAndroid Build Coastguard Worker }; 89*c8dee2aaSAndroid Build Coastguard Worker template <typename T> When(bool condition,const T & value)90*c8dee2aaSAndroid Build Coastguard Worker static GrOptionalUniform<T> When(bool condition, const T& value) { 91*c8dee2aaSAndroid Build Coastguard Worker return {condition, value}; 92*c8dee2aaSAndroid Build Coastguard Worker } 93*c8dee2aaSAndroid Build Coastguard Worker 94*c8dee2aaSAndroid Build Coastguard Worker struct GrIgnoreOptFlags { 95*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrFragmentProcessor> child; 96*c8dee2aaSAndroid Build Coastguard Worker }; IgnoreOptFlags(std::unique_ptr<GrFragmentProcessor> child)97*c8dee2aaSAndroid Build Coastguard Worker static GrIgnoreOptFlags IgnoreOptFlags(std::unique_ptr<GrFragmentProcessor> child) { 98*c8dee2aaSAndroid Build Coastguard Worker return {std::move(child)}; 99*c8dee2aaSAndroid Build Coastguard Worker } 100*c8dee2aaSAndroid Build Coastguard Worker 101*c8dee2aaSAndroid Build Coastguard Worker enum class OptFlags : uint32_t { 102*c8dee2aaSAndroid Build Coastguard Worker kNone = kNone_OptimizationFlags, 103*c8dee2aaSAndroid Build Coastguard Worker kCompatibleWithCoverageAsAlpha = kCompatibleWithCoverageAsAlpha_OptimizationFlag, 104*c8dee2aaSAndroid Build Coastguard Worker kPreservesOpaqueInput = kPreservesOpaqueInput_OptimizationFlag, 105*c8dee2aaSAndroid Build Coastguard Worker kAll = kCompatibleWithCoverageAsAlpha | kPreservesOpaqueInput, 106*c8dee2aaSAndroid Build Coastguard Worker }; 107*c8dee2aaSAndroid Build Coastguard Worker 108*c8dee2aaSAndroid Build Coastguard Worker /** 109*c8dee2aaSAndroid Build Coastguard Worker * Both factories support a single 'input' FP, as well as a collection of other 'child' FPs. 110*c8dee2aaSAndroid Build Coastguard Worker * The 'child' FPs correspond to the children declared in the effect's SkSL. The inputFP is 111*c8dee2aaSAndroid Build Coastguard Worker * optional, and intended for instances that have color filter semantics. This is an implicit 112*c8dee2aaSAndroid Build Coastguard Worker * child - if present, it's evaluated to produce the input color fed to the SkSL. Otherwise, 113*c8dee2aaSAndroid Build Coastguard Worker * the SkSL receives this FP's input color directly. 114*c8dee2aaSAndroid Build Coastguard Worker */ 115*c8dee2aaSAndroid Build Coastguard Worker 116*c8dee2aaSAndroid Build Coastguard Worker /** 117*c8dee2aaSAndroid Build Coastguard Worker * Creates a new fragment processor from an SkRuntimeEffect and a data blob containing values 118*c8dee2aaSAndroid Build Coastguard Worker * for all of the 'uniform' variables in the SkSL source. The layout of the uniforms blob is 119*c8dee2aaSAndroid Build Coastguard Worker * dictated by the SkRuntimeEffect. 120*c8dee2aaSAndroid Build Coastguard Worker */ 121*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<GrSkSLFP> MakeWithData( 122*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkRuntimeEffect> effect, 123*c8dee2aaSAndroid Build Coastguard Worker const char* name, 124*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> dstColorSpace, 125*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrFragmentProcessor> inputFP, 126*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrFragmentProcessor> destColorFP, 127*c8dee2aaSAndroid Build Coastguard Worker const sk_sp<const SkData>& uniforms, 128*c8dee2aaSAndroid Build Coastguard Worker SkSpan<std::unique_ptr<GrFragmentProcessor>> childFPs); 129*c8dee2aaSAndroid Build Coastguard Worker 130*c8dee2aaSAndroid Build Coastguard Worker /* 131*c8dee2aaSAndroid Build Coastguard Worker * Constructs a GrSkSLFP from a series of name-value pairs, corresponding to the children and 132*c8dee2aaSAndroid Build Coastguard Worker * uniform data members of the effect's SkSL. 133*c8dee2aaSAndroid Build Coastguard Worker * The variable length args... must contain all of the children and uniforms expected. 134*c8dee2aaSAndroid Build Coastguard Worker * Each individual argument must be preceded by a name that matches the SkSL name of the value 135*c8dee2aaSAndroid Build Coastguard Worker * being set. For children, the next argument must be a std::unique_ptr<GrFragmentProcessor>. 136*c8dee2aaSAndroid Build Coastguard Worker * For uniforms, the next argument must be data of the correct size and type. 137*c8dee2aaSAndroid Build Coastguard Worker * 138*c8dee2aaSAndroid Build Coastguard Worker * For example, given: 139*c8dee2aaSAndroid Build Coastguard Worker * uniform shader child; 140*c8dee2aaSAndroid Build Coastguard Worker * uniform float scale; 141*c8dee2aaSAndroid Build Coastguard Worker * uniform half2 pt; 142*c8dee2aaSAndroid Build Coastguard Worker * half4 main() { ... } 143*c8dee2aaSAndroid Build Coastguard Worker * 144*c8dee2aaSAndroid Build Coastguard Worker * A call to GrSkSLFP would be formatted like: 145*c8dee2aaSAndroid Build Coastguard Worker * std::unique_ptr<GrFragmentProcessor> child = ...; 146*c8dee2aaSAndroid Build Coastguard Worker * float scaleVal = ...; 147*c8dee2aaSAndroid Build Coastguard Worker * SkV2 ptVal = ...; 148*c8dee2aaSAndroid Build Coastguard Worker * auto fp = GrSkSLFP::Make(effect, "my_effect", nullptr, GrSkSLFP::OptFlags::..., 149*c8dee2aaSAndroid Build Coastguard Worker * "child", std::move(child), 150*c8dee2aaSAndroid Build Coastguard Worker * "scale", scaleVal, 151*c8dee2aaSAndroid Build Coastguard Worker * "pt", ptVal); 152*c8dee2aaSAndroid Build Coastguard Worker * 153*c8dee2aaSAndroid Build Coastguard Worker * The uniforms must appear in the correct order, as must the children. Technically, the two 154*c8dee2aaSAndroid Build Coastguard Worker * lists can be interleaved. In debug builds, the number, names, and sizes of all arguments are 155*c8dee2aaSAndroid Build Coastguard Worker * checked with assertions. In release builds, all checks are elided. In either case, the 156*c8dee2aaSAndroid Build Coastguard Worker * uniform data is directly copied into the footer allocated after the FP. 157*c8dee2aaSAndroid Build Coastguard Worker */ 158*c8dee2aaSAndroid Build Coastguard Worker template <typename... Args> Make(const SkRuntimeEffect * effect,const char * name,std::unique_ptr<GrFragmentProcessor> inputFP,OptFlags optFlags,Args &&...args)159*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<GrSkSLFP> Make(const SkRuntimeEffect* effect, 160*c8dee2aaSAndroid Build Coastguard Worker const char* name, 161*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrFragmentProcessor> inputFP, 162*c8dee2aaSAndroid Build Coastguard Worker OptFlags optFlags, 163*c8dee2aaSAndroid Build Coastguard Worker Args&&... args) { 164*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG 165*c8dee2aaSAndroid Build Coastguard Worker checkArgs(effect->fUniforms.begin(), 166*c8dee2aaSAndroid Build Coastguard Worker effect->fUniforms.end(), 167*c8dee2aaSAndroid Build Coastguard Worker effect->fChildren.begin(), 168*c8dee2aaSAndroid Build Coastguard Worker effect->fChildren.end(), 169*c8dee2aaSAndroid Build Coastguard Worker std::forward<Args>(args)...); 170*c8dee2aaSAndroid Build Coastguard Worker #endif 171*c8dee2aaSAndroid Build Coastguard Worker // This factory is used internally (for "runtime FPs"). We don't pass/know the destination 172*c8dee2aaSAndroid Build Coastguard Worker // color space, so these effects can't use the color transform intrinsics. Callers of this 173*c8dee2aaSAndroid Build Coastguard Worker // factory should instead construct an GrColorSpaceXformEffect as part of the FP tree. 174*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!effect->usesColorTransform()); 175*c8dee2aaSAndroid Build Coastguard Worker 176*c8dee2aaSAndroid Build Coastguard Worker size_t uniformPayloadSize = UniformPayloadSize(effect); 177*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrSkSLFP> fp(new (uniformPayloadSize) GrSkSLFP(sk_ref_sp(effect), 178*c8dee2aaSAndroid Build Coastguard Worker name, optFlags)); 179*c8dee2aaSAndroid Build Coastguard Worker fp->appendArgs(fp->uniformData(), fp->specialized(), std::forward<Args>(args)...); 180*c8dee2aaSAndroid Build Coastguard Worker if (inputFP) { 181*c8dee2aaSAndroid Build Coastguard Worker fp->setInput(std::move(inputFP)); 182*c8dee2aaSAndroid Build Coastguard Worker } 183*c8dee2aaSAndroid Build Coastguard Worker return fp; 184*c8dee2aaSAndroid Build Coastguard Worker } 185*c8dee2aaSAndroid Build Coastguard Worker name()186*c8dee2aaSAndroid Build Coastguard Worker const char* name() const override { return fName; } 187*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrFragmentProcessor> clone() const override; 188*c8dee2aaSAndroid Build Coastguard Worker 189*c8dee2aaSAndroid Build Coastguard Worker private: 190*c8dee2aaSAndroid Build Coastguard Worker class Impl; 191*c8dee2aaSAndroid Build Coastguard Worker 192*c8dee2aaSAndroid Build Coastguard Worker GrSkSLFP(sk_sp<SkRuntimeEffect> effect, const char* name, OptFlags optFlags); 193*c8dee2aaSAndroid Build Coastguard Worker GrSkSLFP(const GrSkSLFP& other); 194*c8dee2aaSAndroid Build Coastguard Worker 195*c8dee2aaSAndroid Build Coastguard Worker static OptimizationFlags DetermineOptimizationFlags(OptFlags of, SkRuntimeEffect* effect); 196*c8dee2aaSAndroid Build Coastguard Worker 197*c8dee2aaSAndroid Build Coastguard Worker void addChild(std::unique_ptr<GrFragmentProcessor> child, bool mergeOptFlags); 198*c8dee2aaSAndroid Build Coastguard Worker void setInput(std::unique_ptr<GrFragmentProcessor> input); 199*c8dee2aaSAndroid Build Coastguard Worker void setDestColorFP(std::unique_ptr<GrFragmentProcessor> destColorFP); 200*c8dee2aaSAndroid Build Coastguard Worker void addColorTransformChildren(SkColorSpace* dstColorSpace); 201*c8dee2aaSAndroid Build Coastguard Worker 202*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override; 203*c8dee2aaSAndroid Build Coastguard Worker 204*c8dee2aaSAndroid Build Coastguard Worker void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override; 205*c8dee2aaSAndroid Build Coastguard Worker 206*c8dee2aaSAndroid Build Coastguard Worker bool onIsEqual(const GrFragmentProcessor&) const override; 207*c8dee2aaSAndroid Build Coastguard Worker 208*c8dee2aaSAndroid Build Coastguard Worker SkPMColor4f constantOutputForConstantInput(const SkPMColor4f&) const override; 209*c8dee2aaSAndroid Build Coastguard Worker uniformCount()210*c8dee2aaSAndroid Build Coastguard Worker size_t uniformCount() const { return fEffect->uniforms().size(); } 211*c8dee2aaSAndroid Build Coastguard Worker 212*c8dee2aaSAndroid Build Coastguard Worker // An instance of GrSkSLFP is always allocated with a payload immediately following the FP. 213*c8dee2aaSAndroid Build Coastguard Worker // First the values of all the uniforms, and then a set of flags (one per uniform). UniformPayloadSize(const SkRuntimeEffect * effect)214*c8dee2aaSAndroid Build Coastguard Worker static size_t UniformPayloadSize(const SkRuntimeEffect* effect) { 215*c8dee2aaSAndroid Build Coastguard Worker return effect->uniformSize() + effect->uniforms().size() * sizeof(Specialized); 216*c8dee2aaSAndroid Build Coastguard Worker } 217*c8dee2aaSAndroid Build Coastguard Worker uniformData()218*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* uniformData() const { return reinterpret_cast<const uint8_t*>(this + 1); } uniformData()219*c8dee2aaSAndroid Build Coastguard Worker uint8_t* uniformData() { return reinterpret_cast< uint8_t*>(this + 1); } 220*c8dee2aaSAndroid Build Coastguard Worker 221*c8dee2aaSAndroid Build Coastguard Worker using Specialized = GrGLSLProgramDataManager::Specialized; 222*c8dee2aaSAndroid Build Coastguard Worker specialized()223*c8dee2aaSAndroid Build Coastguard Worker const Specialized* specialized() const { 224*c8dee2aaSAndroid Build Coastguard Worker return reinterpret_cast<const Specialized*>(this->uniformData() + fUniformSize); 225*c8dee2aaSAndroid Build Coastguard Worker } specialized()226*c8dee2aaSAndroid Build Coastguard Worker Specialized* specialized() { 227*c8dee2aaSAndroid Build Coastguard Worker return reinterpret_cast<Specialized*>(this->uniformData() + fUniformSize); 228*c8dee2aaSAndroid Build Coastguard Worker } 229*c8dee2aaSAndroid Build Coastguard Worker 230*c8dee2aaSAndroid Build Coastguard Worker // Helpers to attach variadic template args to a newly constructed FP: 231*c8dee2aaSAndroid Build Coastguard Worker appendArgs(uint8_t * uniformDataPtr,Specialized * specializedPtr)232*c8dee2aaSAndroid Build Coastguard Worker void appendArgs(uint8_t* uniformDataPtr, Specialized* specializedPtr) { 233*c8dee2aaSAndroid Build Coastguard Worker // Base case -- no more args to append, so we're done 234*c8dee2aaSAndroid Build Coastguard Worker } 235*c8dee2aaSAndroid Build Coastguard Worker template <typename... Args> appendArgs(uint8_t * uniformDataPtr,Specialized * specializedPtr,const char * name,std::unique_ptr<GrFragmentProcessor> && child,Args &&...remainder)236*c8dee2aaSAndroid Build Coastguard Worker void appendArgs(uint8_t* uniformDataPtr, 237*c8dee2aaSAndroid Build Coastguard Worker Specialized* specializedPtr, 238*c8dee2aaSAndroid Build Coastguard Worker const char* name, 239*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrFragmentProcessor>&& child, 240*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 241*c8dee2aaSAndroid Build Coastguard Worker // Child FP case -- register the child, then continue processing the remaining arguments. 242*c8dee2aaSAndroid Build Coastguard Worker // Children aren't "uniforms" here, so the data & flags pointers don't advance. 243*c8dee2aaSAndroid Build Coastguard Worker this->addChild(std::move(child), /*mergeOptFlags=*/true); 244*c8dee2aaSAndroid Build Coastguard Worker this->appendArgs(uniformDataPtr, specializedPtr, std::forward<Args>(remainder)...); 245*c8dee2aaSAndroid Build Coastguard Worker } 246*c8dee2aaSAndroid Build Coastguard Worker // As above, but we don't merge in the child's optimization flags 247*c8dee2aaSAndroid Build Coastguard Worker template <typename... Args> appendArgs(uint8_t * uniformDataPtr,Specialized * specializedPtr,const char * name,GrIgnoreOptFlags && child,Args &&...remainder)248*c8dee2aaSAndroid Build Coastguard Worker void appendArgs(uint8_t* uniformDataPtr, 249*c8dee2aaSAndroid Build Coastguard Worker Specialized* specializedPtr, 250*c8dee2aaSAndroid Build Coastguard Worker const char* name, 251*c8dee2aaSAndroid Build Coastguard Worker GrIgnoreOptFlags&& child, 252*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 253*c8dee2aaSAndroid Build Coastguard Worker // Child FP case -- register the child, then continue processing the remaining arguments. 254*c8dee2aaSAndroid Build Coastguard Worker // Children aren't "uniforms" here, so the data & flags pointers don't advance. 255*c8dee2aaSAndroid Build Coastguard Worker this->addChild(std::move(child.child), /*mergeOptFlags=*/false); 256*c8dee2aaSAndroid Build Coastguard Worker this->appendArgs(uniformDataPtr, specializedPtr, std::forward<Args>(remainder)...); 257*c8dee2aaSAndroid Build Coastguard Worker } 258*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> appendArgs(uint8_t * uniformDataPtr,Specialized * specializedPtr,const char * name,const GrSpecializedUniform<T> & val,Args &&...remainder)259*c8dee2aaSAndroid Build Coastguard Worker void appendArgs(uint8_t* uniformDataPtr, 260*c8dee2aaSAndroid Build Coastguard Worker Specialized* specializedPtr, 261*c8dee2aaSAndroid Build Coastguard Worker const char* name, 262*c8dee2aaSAndroid Build Coastguard Worker const GrSpecializedUniform<T>& val, 263*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 264*c8dee2aaSAndroid Build Coastguard Worker // Specialized uniform case -- This just handles the specialization logic. If we want to 265*c8dee2aaSAndroid Build Coastguard Worker // specialize on this particular value, set the flag. Then, continue processing the actual 266*c8dee2aaSAndroid Build Coastguard Worker // value (by just peeling off the wrapper). This lets our generic `const T&` case (below) 267*c8dee2aaSAndroid Build Coastguard Worker // handle copying the data into our uniform block, and advancing the per-value uniform 268*c8dee2aaSAndroid Build Coastguard Worker // data and flags pointers. 269*c8dee2aaSAndroid Build Coastguard Worker if (val.specialize) { 270*c8dee2aaSAndroid Build Coastguard Worker *specializedPtr = Specialized::kYes; 271*c8dee2aaSAndroid Build Coastguard Worker } 272*c8dee2aaSAndroid Build Coastguard Worker this->appendArgs( 273*c8dee2aaSAndroid Build Coastguard Worker uniformDataPtr, specializedPtr, name, val.value, std::forward<Args>(remainder)...); 274*c8dee2aaSAndroid Build Coastguard Worker } 275*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> appendArgs(uint8_t * uniformDataPtr,Specialized * specializedPtr,const char * name,const GrOptionalUniform<T> & val,Args &&...remainder)276*c8dee2aaSAndroid Build Coastguard Worker void appendArgs(uint8_t* uniformDataPtr, 277*c8dee2aaSAndroid Build Coastguard Worker Specialized* specializedPtr, 278*c8dee2aaSAndroid Build Coastguard Worker const char* name, 279*c8dee2aaSAndroid Build Coastguard Worker const GrOptionalUniform<T>& val, 280*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 281*c8dee2aaSAndroid Build Coastguard Worker // Optional uniform case. Copy the data and advance pointers, but only if the uniform is 282*c8dee2aaSAndroid Build Coastguard Worker // enabled. Then proceed as normal. 283*c8dee2aaSAndroid Build Coastguard Worker if (val.enabled) { 284*c8dee2aaSAndroid Build Coastguard Worker memcpy(uniformDataPtr, &val.value, sizeof(val.value)); 285*c8dee2aaSAndroid Build Coastguard Worker uniformDataPtr += sizeof(val.value); 286*c8dee2aaSAndroid Build Coastguard Worker specializedPtr++; 287*c8dee2aaSAndroid Build Coastguard Worker } 288*c8dee2aaSAndroid Build Coastguard Worker 289*c8dee2aaSAndroid Build Coastguard Worker this->appendArgs(uniformDataPtr, specializedPtr, std::forward<Args>(remainder)...); 290*c8dee2aaSAndroid Build Coastguard Worker } 291*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> appendArgs(uint8_t * uniformDataPtr,Specialized * specializedPtr,const char * name,SkSpan<T> val,Args &&...remainder)292*c8dee2aaSAndroid Build Coastguard Worker void appendArgs(uint8_t* uniformDataPtr, 293*c8dee2aaSAndroid Build Coastguard Worker Specialized* specializedPtr, 294*c8dee2aaSAndroid Build Coastguard Worker const char* name, 295*c8dee2aaSAndroid Build Coastguard Worker SkSpan<T> val, 296*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 297*c8dee2aaSAndroid Build Coastguard Worker // Uniform array case -- We copy the supplied values into our uniform data area, 298*c8dee2aaSAndroid Build Coastguard Worker // then advance our uniform data and flags pointers. 299*c8dee2aaSAndroid Build Coastguard Worker memcpy(uniformDataPtr, val.data(), val.size_bytes()); 300*c8dee2aaSAndroid Build Coastguard Worker uniformDataPtr += val.size_bytes(); 301*c8dee2aaSAndroid Build Coastguard Worker specializedPtr++; 302*c8dee2aaSAndroid Build Coastguard Worker this->appendArgs(uniformDataPtr, specializedPtr, std::forward<Args>(remainder)...); 303*c8dee2aaSAndroid Build Coastguard Worker } 304*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> appendArgs(uint8_t * uniformDataPtr,Specialized * specializedPtr,const char * name,const T & val,Args &&...remainder)305*c8dee2aaSAndroid Build Coastguard Worker void appendArgs(uint8_t* uniformDataPtr, 306*c8dee2aaSAndroid Build Coastguard Worker Specialized* specializedPtr, 307*c8dee2aaSAndroid Build Coastguard Worker const char* name, 308*c8dee2aaSAndroid Build Coastguard Worker const T& val, 309*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 310*c8dee2aaSAndroid Build Coastguard Worker // Raw uniform value case -- We copy the supplied value into our uniform data area, 311*c8dee2aaSAndroid Build Coastguard Worker // then advance our uniform data and flags pointers. 312*c8dee2aaSAndroid Build Coastguard Worker memcpy(uniformDataPtr, &val, sizeof(val)); 313*c8dee2aaSAndroid Build Coastguard Worker uniformDataPtr += sizeof(val); 314*c8dee2aaSAndroid Build Coastguard Worker specializedPtr++; 315*c8dee2aaSAndroid Build Coastguard Worker this->appendArgs(uniformDataPtr, specializedPtr, std::forward<Args>(remainder)...); 316*c8dee2aaSAndroid Build Coastguard Worker } 317*c8dee2aaSAndroid Build Coastguard Worker 318*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG 319*c8dee2aaSAndroid Build Coastguard Worker using child_iterator = std::vector<SkRuntimeEffect::Child>::const_iterator; 320*c8dee2aaSAndroid Build Coastguard Worker using uniform_iterator = std::vector<SkRuntimeEffect::Uniform>::const_iterator; 321*c8dee2aaSAndroid Build Coastguard Worker 322*c8dee2aaSAndroid Build Coastguard Worker // Validates that all args passed to the template factory have the right names, sizes, and types checkArgs(uniform_iterator uIter,uniform_iterator uEnd,child_iterator cIter,child_iterator cEnd)323*c8dee2aaSAndroid Build Coastguard Worker static void checkArgs(uniform_iterator uIter, 324*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 325*c8dee2aaSAndroid Build Coastguard Worker child_iterator cIter, 326*c8dee2aaSAndroid Build Coastguard Worker child_iterator cEnd) { 327*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(uIter == uEnd, 328*c8dee2aaSAndroid Build Coastguard Worker "Expected more uniforms, starting with '%.*s'", 329*c8dee2aaSAndroid Build Coastguard Worker (int)uIter->name.size(), uIter->name.data()); 330*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(cIter == cEnd, "Expected more children, starting with '%.*s'", 331*c8dee2aaSAndroid Build Coastguard Worker (int)cIter->name.size(), cIter->name.data()); 332*c8dee2aaSAndroid Build Coastguard Worker } checkOneChild(child_iterator cIter,child_iterator cEnd,const char * name)333*c8dee2aaSAndroid Build Coastguard Worker static void checkOneChild(child_iterator cIter, child_iterator cEnd, const char* name) { 334*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(cIter != cEnd, "Too many children, wasn't expecting '%s'", name); 335*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(cIter->name == name, 336*c8dee2aaSAndroid Build Coastguard Worker "Expected child '%.*s', got '%s' instead", 337*c8dee2aaSAndroid Build Coastguard Worker (int)cIter->name.size(), cIter->name.data(), name); 338*c8dee2aaSAndroid Build Coastguard Worker } 339*c8dee2aaSAndroid Build Coastguard Worker template <typename... Args> checkArgs(uniform_iterator uIter,uniform_iterator uEnd,child_iterator cIter,child_iterator cEnd,const char * name,std::unique_ptr<GrFragmentProcessor> && child,Args &&...remainder)340*c8dee2aaSAndroid Build Coastguard Worker static void checkArgs(uniform_iterator uIter, 341*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 342*c8dee2aaSAndroid Build Coastguard Worker child_iterator cIter, 343*c8dee2aaSAndroid Build Coastguard Worker child_iterator cEnd, 344*c8dee2aaSAndroid Build Coastguard Worker const char* name, 345*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrFragmentProcessor>&& child, 346*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 347*c8dee2aaSAndroid Build Coastguard Worker // NOTE: This function (necessarily) gets an rvalue reference to child, but deliberately 348*c8dee2aaSAndroid Build Coastguard Worker // does not use it. We leave it intact, and our caller (Make) will pass another rvalue 349*c8dee2aaSAndroid Build Coastguard Worker // reference to appendArgs, which will then move it to call addChild. 350*c8dee2aaSAndroid Build Coastguard Worker checkOneChild(cIter, cEnd, name); 351*c8dee2aaSAndroid Build Coastguard Worker checkArgs(uIter, uEnd, ++cIter, cEnd, std::forward<Args>(remainder)...); 352*c8dee2aaSAndroid Build Coastguard Worker } 353*c8dee2aaSAndroid Build Coastguard Worker template <typename... Args> checkArgs(uniform_iterator uIter,uniform_iterator uEnd,child_iterator cIter,child_iterator cEnd,const char * name,GrIgnoreOptFlags && child,Args &&...remainder)354*c8dee2aaSAndroid Build Coastguard Worker static void checkArgs(uniform_iterator uIter, 355*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 356*c8dee2aaSAndroid Build Coastguard Worker child_iterator cIter, 357*c8dee2aaSAndroid Build Coastguard Worker child_iterator cEnd, 358*c8dee2aaSAndroid Build Coastguard Worker const char* name, 359*c8dee2aaSAndroid Build Coastguard Worker GrIgnoreOptFlags&& child, 360*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 361*c8dee2aaSAndroid Build Coastguard Worker // NOTE: This function (necessarily) gets an rvalue reference to child, but deliberately 362*c8dee2aaSAndroid Build Coastguard Worker // does not use it. We leave it intact, and our caller (Make) will pass another rvalue 363*c8dee2aaSAndroid Build Coastguard Worker // reference to appendArgs, which will then move it to call addChild. 364*c8dee2aaSAndroid Build Coastguard Worker checkOneChild(cIter, cEnd, name); 365*c8dee2aaSAndroid Build Coastguard Worker checkArgs(uIter, uEnd, ++cIter, cEnd, std::forward<Args>(remainder)...); 366*c8dee2aaSAndroid Build Coastguard Worker } 367*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> checkArgs(uniform_iterator uIter,uniform_iterator uEnd,child_iterator cIter,child_iterator cEnd,const char * name,const GrSpecializedUniform<T> & val,Args &&...remainder)368*c8dee2aaSAndroid Build Coastguard Worker static void checkArgs(uniform_iterator uIter, 369*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 370*c8dee2aaSAndroid Build Coastguard Worker child_iterator cIter, 371*c8dee2aaSAndroid Build Coastguard Worker child_iterator cEnd, 372*c8dee2aaSAndroid Build Coastguard Worker const char* name, 373*c8dee2aaSAndroid Build Coastguard Worker const GrSpecializedUniform<T>& val, 374*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 375*c8dee2aaSAndroid Build Coastguard Worker static_assert(!std::is_array<T>::value); // No specializing arrays 376*c8dee2aaSAndroid Build Coastguard Worker checkArgs(uIter, uEnd, cIter, cEnd, name, val.value, std::forward<Args>(remainder)...); 377*c8dee2aaSAndroid Build Coastguard Worker } 378*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> checkArgs(uniform_iterator uIter,uniform_iterator uEnd,child_iterator cIter,child_iterator cEnd,const char * name,const GrOptionalUniform<T> & val,Args &&...remainder)379*c8dee2aaSAndroid Build Coastguard Worker static void checkArgs(uniform_iterator uIter, 380*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 381*c8dee2aaSAndroid Build Coastguard Worker child_iterator cIter, 382*c8dee2aaSAndroid Build Coastguard Worker child_iterator cEnd, 383*c8dee2aaSAndroid Build Coastguard Worker const char* name, 384*c8dee2aaSAndroid Build Coastguard Worker const GrOptionalUniform<T>& val, 385*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 386*c8dee2aaSAndroid Build Coastguard Worker if (val.enabled) { 387*c8dee2aaSAndroid Build Coastguard Worker checkArgs(uIter, uEnd, cIter, cEnd, name, val.value, std::forward<Args>(remainder)...); 388*c8dee2aaSAndroid Build Coastguard Worker } else { 389*c8dee2aaSAndroid Build Coastguard Worker checkArgs(uIter, uEnd, cIter, cEnd, std::forward<Args>(remainder)...); 390*c8dee2aaSAndroid Build Coastguard Worker } 391*c8dee2aaSAndroid Build Coastguard Worker } 392*c8dee2aaSAndroid Build Coastguard Worker template <typename T> checkOneUniform(uniform_iterator uIter,uniform_iterator uEnd,const char * name,const T *,size_t valSize)393*c8dee2aaSAndroid Build Coastguard Worker static void checkOneUniform(uniform_iterator uIter, 394*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 395*c8dee2aaSAndroid Build Coastguard Worker const char* name, 396*c8dee2aaSAndroid Build Coastguard Worker const T* /*val*/, 397*c8dee2aaSAndroid Build Coastguard Worker size_t valSize) { 398*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(uIter != uEnd, "Too many uniforms, wasn't expecting '%s'", name); 399*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(uIter->name == name, 400*c8dee2aaSAndroid Build Coastguard Worker "Expected uniform '%.*s', got '%s' instead", 401*c8dee2aaSAndroid Build Coastguard Worker (int)uIter->name.size(), uIter->name.data(), name); 402*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(uIter->sizeInBytes() == valSize, 403*c8dee2aaSAndroid Build Coastguard Worker "Expected uniform '%s' to be %zu bytes, got %zu instead", 404*c8dee2aaSAndroid Build Coastguard Worker name, uIter->sizeInBytes(), valSize); 405*c8dee2aaSAndroid Build Coastguard Worker SkASSERTF(GrFPUniformType<T>::value == uIter->type, 406*c8dee2aaSAndroid Build Coastguard Worker "Wrong type for uniform '%s'", 407*c8dee2aaSAndroid Build Coastguard Worker name); 408*c8dee2aaSAndroid Build Coastguard Worker } 409*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> checkArgs(uniform_iterator uIter,uniform_iterator uEnd,child_iterator cIter,child_iterator cEnd,const char * name,SkSpan<T> val,Args &&...remainder)410*c8dee2aaSAndroid Build Coastguard Worker static void checkArgs(uniform_iterator uIter, 411*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 412*c8dee2aaSAndroid Build Coastguard Worker child_iterator cIter, 413*c8dee2aaSAndroid Build Coastguard Worker child_iterator cEnd, 414*c8dee2aaSAndroid Build Coastguard Worker const char* name, 415*c8dee2aaSAndroid Build Coastguard Worker SkSpan<T> val, 416*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 417*c8dee2aaSAndroid Build Coastguard Worker checkOneUniform(uIter, uEnd, name, val.data(), val.size_bytes()); 418*c8dee2aaSAndroid Build Coastguard Worker checkArgs(++uIter, uEnd, cIter, cEnd, std::forward<Args>(remainder)...); 419*c8dee2aaSAndroid Build Coastguard Worker } 420*c8dee2aaSAndroid Build Coastguard Worker template <typename T, typename... Args> checkArgs(uniform_iterator uIter,uniform_iterator uEnd,child_iterator cIter,child_iterator cEnd,const char * name,const T & val,Args &&...remainder)421*c8dee2aaSAndroid Build Coastguard Worker static void checkArgs(uniform_iterator uIter, 422*c8dee2aaSAndroid Build Coastguard Worker uniform_iterator uEnd, 423*c8dee2aaSAndroid Build Coastguard Worker child_iterator cIter, 424*c8dee2aaSAndroid Build Coastguard Worker child_iterator cEnd, 425*c8dee2aaSAndroid Build Coastguard Worker const char* name, 426*c8dee2aaSAndroid Build Coastguard Worker const T& val, 427*c8dee2aaSAndroid Build Coastguard Worker Args&&... remainder) { 428*c8dee2aaSAndroid Build Coastguard Worker checkOneUniform(uIter, uEnd, name, &val, sizeof(val)); 429*c8dee2aaSAndroid Build Coastguard Worker checkArgs(++uIter, uEnd, cIter, cEnd, std::forward<Args>(remainder)...); 430*c8dee2aaSAndroid Build Coastguard Worker } 431*c8dee2aaSAndroid Build Coastguard Worker #endif 432*c8dee2aaSAndroid Build Coastguard Worker 433*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkRuntimeEffect> fEffect; 434*c8dee2aaSAndroid Build Coastguard Worker const char* fName; 435*c8dee2aaSAndroid Build Coastguard Worker uint32_t fUniformSize; 436*c8dee2aaSAndroid Build Coastguard Worker int fInputChildIndex = -1; 437*c8dee2aaSAndroid Build Coastguard Worker int fDestColorChildIndex = -1; 438*c8dee2aaSAndroid Build Coastguard Worker int fToLinearSrgbChildIndex = -1; 439*c8dee2aaSAndroid Build Coastguard Worker int fFromLinearSrgbChildIndex = -1; 440*c8dee2aaSAndroid Build Coastguard Worker 441*c8dee2aaSAndroid Build Coastguard Worker GR_DECLARE_FRAGMENT_PROCESSOR_TEST 442*c8dee2aaSAndroid Build Coastguard Worker 443*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrFragmentProcessor; 444*c8dee2aaSAndroid Build Coastguard Worker 445*c8dee2aaSAndroid Build Coastguard Worker friend class GrSkSLFPFactory; 446*c8dee2aaSAndroid Build Coastguard Worker }; 447*c8dee2aaSAndroid Build Coastguard Worker 448*c8dee2aaSAndroid Build Coastguard Worker SK_MAKE_BITFIELD_CLASS_OPS(GrSkSLFP::OptFlags) 449*c8dee2aaSAndroid Build Coastguard Worker 450*c8dee2aaSAndroid Build Coastguard Worker #endif 451