skia2/include/effects/SkRuntimeEffect.h
Brian Osman bd4f872d69 Handle runtime effect shader errors better
- Expose shader error handler on GrBaseContextPriv
- Use that to report errors that happen during (late) SkSL conversion
- Remove various asserts. We expect these functions not to fail, but
  they absolutely can for any kind of error that gets past the first
  compile in SkRuntimeEffect::Make. We'll still make a GLSLFP, but it
  won't inject any code, so the resulting shader will *also* fail to
  compile. Injecting our own errors first gives the user a better idea
  what's actually broken.
- SkSLSlide also reports errors via the error handler now, too.

Change-Id: I4b871cdaa5e3217b042ebf000bb7474afaeab04c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/275679
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2020-03-06 21:32:31 +00:00

156 lines
4.5 KiB
C++

/*
* 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/SkString.h"
#include <vector>
#if SK_SUPPORT_GPU
#include "include/gpu/GrContextOptions.h"
#include "include/private/GrTypesPriv.h"
#endif
class GrShaderCaps;
class SkColorFilter;
class SkMatrix;
class SkShader;
namespace SkSL {
class ByteCode;
struct PipelineStageArgs;
struct Program;
class SharedCompiler;
}
/*
* SkRuntimeEffect supports creating custom SkShader and SkColorFilter objects using Skia's SkSL
* shading language.
* *
* This API is experimental and subject to change.
*/
class SK_API SkRuntimeEffect : public SkRefCnt {
public:
struct Variable {
enum class Qualifier {
kUniform,
kIn,
};
enum class Type {
kBool,
kInt,
kFloat,
kFloat2,
kFloat3,
kFloat4,
kFloat2x2,
kFloat3x3,
kFloat4x4,
};
enum Flags {
kArray_Flag = 0x1,
};
SkString fName;
size_t fOffset;
Qualifier fQualifier;
Type fType;
int fCount;
uint32_t fFlags;
#if SK_SUPPORT_GPU
GrSLType fGPUType;
#endif
bool isArray() const { return SkToBool(fFlags & kArray_Flag); }
size_t sizeInBytes() const;
};
// [Effect, ErrorText]
// If successful, Effect != nullptr, otherwise, ErrorText contains the reason for failure.
using EffectResult = std::tuple<sk_sp<SkRuntimeEffect>, SkString>;
static EffectResult Make(SkString sksl);
sk_sp<SkShader> makeShader(sk_sp<SkData> inputs, sk_sp<SkShader> children[], size_t childCount,
const SkMatrix* localMatrix, bool isOpaque);
sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs, sk_sp<SkColorFilter> children[],
size_t childCount);
sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs);
const SkString& source() const { return fSkSL; }
uint32_t hash() const { return fHash; }
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 'in' and 'uniform' variables. When calling makeColorFilter or
// makeShader, provide an SkData of this size, containing values for all of those variables.
size_t inputSize() const;
// Combined size of just the 'uniform' variables.
size_t uniformSize() const { return fUniformSize; }
ConstIterable<Variable> inputs() const { return ConstIterable<Variable>(fInAndUniformVars); }
ConstIterable<SkString> children() const { return ConstIterable<SkString>(fChildren); }
#if SK_SUPPORT_GPU
// This re-compiles the program from scratch, using the supplied shader caps.
// This is necessary to get the correct values of settings.
bool toPipelineStage(const void* inputs, const GrShaderCaps* shaderCaps,
GrContextOptions::ShaderErrorHandler* errorHandler,
SkSL::PipelineStageArgs* outArgs);
#endif
// [ByteCode, ErrorText]
// If successful, ByteCode != nullptr, otherwise, ErrorText contains the reason for failure.
using ByteCodeResult = std::tuple<std::unique_ptr<SkSL::ByteCode>, SkString>;
ByteCodeResult toByteCode(const void* inputs);
static void RegisterFlattenables();
~SkRuntimeEffect();
private:
SkRuntimeEffect(SkString sksl, std::unique_ptr<SkSL::Program> baseProgram,
std::vector<Variable>&& inAndUniformVars, std::vector<SkString>&& children,
size_t uniformSize);
using SpecializeResult = std::tuple<std::unique_ptr<SkSL::Program>, SkString>;
SpecializeResult specialize(SkSL::Program& baseProgram, const void* inputs,
const SkSL::SharedCompiler&);
uint32_t fHash;
SkString fSkSL;
std::unique_ptr<SkSL::Program> fBaseProgram;
std::vector<Variable> fInAndUniformVars;
std::vector<SkString> fChildren;
size_t fUniformSize;
};
#endif