60#define RETURN_FAILURE(...) return Result{nullptr, SkStringPrintf(__VA_ARGS__)}
62#define RETURN_ERROR(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))
64#define RETURN_SUCCESS return std::make_tuple(true, SkString{})
69static std::vector<Uniform>::iterator
find_uniform(std::vector<Uniform>& uniforms,
70 std::string_view
name) {
71 return std::find_if(uniforms.begin(), uniforms.end(),
75static std::tuple<bool, SkString>
77 std::vector<Uniform>* uniforms,
78 std::vector<Child>* children,
81 bool foundMain =
false;
93 if (var.modifierFlags().isUniform()) {
94 if (var.type().isEffectChild()) {
101 const auto& context = *program.
fContext;
102 if (iter == uniforms->end()) {
105 uniforms->back().flags |= stage;
108 size_t ignoredOffset = 0;
111 if (uniform.isArray() != iter->isArray() ||
112 uniform.type != iter->type ||
113 uniform.count != iter->count) {
116 " in vertex and fragment shaders.",
117 (
int)var.name().size(), var.name().data())};
119 if (uniform.isColor() != iter->isColor()) {
122 " layout in vertex and fragment shaders.",
123 (
int)var.name().size(), var.name().data())};
125 (*iter).flags |= stage;
132 return {
false,
SkString(
"No main function found.")};
145 SkASSERT(decl.parameters().size() == 1 || decl.parameters().size() == 2);
146 if (decl.parameters().size() == 1) {
152 return paramType.
matches(*fsProgram.
fContext->fTypes.fHalf4) ? ColorType::kHalf4
153 : ColorType::kFloat4;
164 if (
name.isEmpty()) {
167 for (
size_t i = 0;
i <
name.size(); ++
i) {
168 if (
name[
i] !=
'_' && !std::isalnum(
name[
i], std::locale::classic())) {
211std::tuple<bool, SkString>
225 if (attributes.
empty()) {
234 RETURN_ERROR(
"Vertex stride must be a non-zero multiple of %zu.",
240 for (
const auto&
a : attributes) {
242 RETURN_ERROR(
"Attribute offset must be a multiple of %zu.",
248 RETURN_ERROR(
"Attribute offset plus size cannot exceed stride.");
255 uint32_t* deadVaryingMask) {
258 using namespace SkSL;
259 static constexpr int kFailed = -2;
267 int passthroughFieldIndex()
const {
return fPassthroughFieldIndex; }
269 uint32_t fieldUseMask()
const {
return fFieldUseMask; }
275 if (def.type().name() ==
"Varyings") {
276 fVaryingsType = &def.
type();
285 SkASSERT(fVaryingsType && fVaryingsType->matches(fVaryings->type()));
303 if (fPassthroughFieldIndex == kFailed) {
316 this->passthroughFailed();
319 const auto& fa = rs.expression()->as<
FieldAccess>();
321 this->passthroughFailed();
325 if (baseRef.variable() != fVaryings) {
326 this->passthroughFailed();
329 if (fPassthroughFieldIndex >= 0) {
332 if (fa.fieldIndex() != fPassthroughFieldIndex) {
333 this->passthroughFailed();
340 const Field& field = fVaryings->type().fields()[fa.fieldIndex()];
342 this->passthroughFailed();
345 fPassthroughFieldIndex = fa.fieldIndex();
353 if (!fVaryingsType) {
360 if (!fa.base()->type().matches(*fVaryingsType)) {
363 fFieldUseMask |= 1 << fa.fieldIndex();
368 void passthroughFailed() {
369 if (fPassthroughFieldIndex >= 0) {
370 fFieldUseMask |= 1 << fPassthroughFieldIndex;
372 fPassthroughFieldIndex = kFailed;
376 const Type* fVaryingsType =
nullptr;
377 const Variable* fVaryings =
nullptr;
378 int fPassthroughFieldIndex = -1;
379 bool fInMain =
false;
380 uint32_t fFieldUseMask = 0;
385 *deadVaryingMask = ~v.fieldUseMask();
386 return v.passthroughFieldIndex();
419 SkString attributesStruct(
"struct Attributes {\n");
423 attributesStruct.
append(
"};\n");
425 bool userProvidedPositionVarying =
false;
426 for (
const auto& v : varyings) {
427 if (v.name.equals(
"position")) {
429 return {
nullptr,
SkString(
"Varying \"position\" must have type float2.")};
431 userProvidedPositionVarying =
true;
436 if (!userProvidedPositionVarying) {
442 for (
const auto& v : varyings) {
446 varyings = tempVaryings;
449 SkString varyingStruct(
"struct Varyings {\n");
450 for (
const auto& v : varyings) {
453 varyingStruct.
append(
"};\n");
482 return {
nullptr,
error};
487 RETURN_FAILURE(
"\"%s\" is not a valid attribute name.",
a.name.c_str());
495 for (
const auto& v : varyings) {
497 return {
nullptr,
SkStringPrintf(
"\"%s\" is not a valid varying name.", v.name.c_str())};
513 std::unique_ptr<SkSL::Program> vsProgram =
compiler.convertProgram(
515 std::string(vs.
c_str()),
525 SkMeshSpecification::Uniform::Flags::kVertex_Flag,
528 return {
nullptr, std::move(
error)};
532 RETURN_FAILURE(
"Color transform intrinsics are not permitted in custom mesh shaders");
535 std::unique_ptr<SkSL::Program> fsProgram =
compiler.convertProgram(
537 std::string(fs.
c_str()),
548 SkMeshSpecification::Uniform::Flags::kFragment_Flag,
551 return {
nullptr, std::move(
error)};
555 RETURN_FAILURE(
"Color transform intrinsics are not permitted in custom mesh shaders");
560 if (ct == ColorType::kNone) {
565 return {
nullptr,
SkString{
"Must provide a color space if FS returns a color."}};
568 return {
nullptr,
SkString{
"Must provide a valid alpha type if FS returns a color."}};
572 uint32_t deadVaryingMask;
573 int passthroughLocalCoordsVaryingIndex =
576 if (passthroughLocalCoordsVaryingIndex >= 0) {
583 passthroughLocalCoordsVaryingIndex,
587 std::move(vsProgram),
588 std::move(fsProgram),
597SkMeshSpecification::SkMeshSpecification(
601 int passthroughLocalCoordsVaryingIndex,
602 uint32_t deadVaryingMask,
603 std::vector<Uniform> uniforms,
604 std::vector<Child> children,
605 std::unique_ptr<const SkSL::Program> vs,
606 std::unique_ptr<const SkSL::Program> fs,
610 : fAttributes(attributes.
begin(), attributes.
end())
611 , fVaryings(varyings.
begin(), varyings.
end())
612 , fUniforms(
std::move(uniforms))
613 , fChildren(
std::move(children))
617 , fPassthroughLocalCoordsVaryingIndex(passthroughLocalCoordsVaryingIndex)
618 , fDeadVaryingMask(deadVaryingMask)
620 , fColorSpace(
std::move(cs))
628 for (
const auto&
a : fAttributes) {
635 uint64_t csHash = fColorSpace ? fColorSpace->
hash() : 0;
638 auto atInt =
static_cast<uint32_t
>(fAlphaType);
643 return fUniforms.empty() ? 0
644 :
SkAlign4(fUniforms.back().offset + fUniforms.back().sizeInBytes());
648 for (
const Uniform& uniform : fUniforms) {
649 if (uniform.name ==
name) {
657 for (
const Child& child : fChildren) {
658 if (child.name ==
name) {
666 for (
const Attribute& attr : fAttributes) {
667 if (
name == attr.name.c_str()) {
675 for (
const Varying& varying : fVaryings) {
676 if (
name == varying.name.c_str()) {
705 mesh.fVB = std::move(vb);
711 auto [valid, msg] =
mesh.validate();
715 return {std::move(
mesh), std::move(msg)};
732 return {{},
SkString{
"An index buffer is required."}};
737 mesh.fVB = std::move(vb);
740 mesh.fIB = std::move(ib);
746 auto [valid, msg] =
mesh.validate();
750 return {std::move(
mesh), std::move(msg)};
767std::tuple<bool, SkString> SkMesh::validate()
const {
768#define FAIL_MESH_VALIDATE(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))
779 "but the mesh supplies %d.",
784 for (
int index = 0; index < fChildren.size(); ++index) {
786 if (fChildren[index].
type().has_value()) {
787 if (meshSpecChild.
type != fChildren[index].type()) {
789 (
int)meshSpecChild.
name.size(), meshSpecChild.
name.data(),
800 size_t vsize = sm.
mul(fSpec->
stride(), fVCount);
801 if (sm.
add(vsize, fVOffset) > vb->size()) {
802 FAIL_MESH_VALIDATE(
"The vertex buffer offset and vertex count reads beyond the end of the"
806 if (fVOffset%fSpec->
stride() != 0) {
807 FAIL_MESH_VALIDATE(
"The vertex offset (%zu) must be a multiple of the vertex stride (%zu).",
813 if (!fUniforms || fUniforms->
size() < uniformSize) {
820 auto modeToStr = [](
Mode m) {
834 size_t isize = sm.
mul(
sizeof(uint16_t), fICount);
835 if (sm.
add(isize, fIOffset) > ib->size()) {
836 FAIL_MESH_VALIDATE(
"The index buffer offset and index count reads beyond the end of the"
858#undef FAIL_MESH_VALIDATE
898 const void*
data = ib->peek();
914 const void*
data = vb->peek();
static constexpr bool SkIsAlign2(T x)
static constexpr bool SkIsAlign4(T x)
static constexpr T SkAlign4(T x)
@ kUnknown_SkAlphaType
uninitialized
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
static bool ok(int result)
constexpr bool SkIsPow2(T value)
SkMesh::VertexBuffer VertexBuffer
static const char * attribute_type_string(Attribute::Type type)
#define FAIL_MESH_VALIDATE(...)
static size_t min_vcount_for_mode(SkMesh::Mode mode)
SkMeshSpecification::Attribute Attribute
std::tuple< bool, SkString > check_vertex_offsets_and_stride(SkSpan< const Attribute > attributes, size_t stride)
static std::tuple< bool, SkString > gather_uniforms_and_check_for_main(const SkSL::Program &program, std::vector< Uniform > *uniforms, std::vector< Child > *children, SkMeshSpecification::Uniform::Flags stage, size_t *offset)
static std::vector< Uniform >::iterator find_uniform(std::vector< Uniform > &uniforms, std::string_view name)
static bool check_update(const void *data, size_t offset, size_t size, size_t bufferSize)
static size_t attribute_type_size(Attribute::Type type)
SkMeshSpecification::Varying Varying
static bool check_name(const SkString &name)
#define RETURN_FAILURE(...)
int check_for_passthrough_local_coords_and_dead_varyings(const SkSL::Program &fsProgram, uint32_t *deadVaryingMask)
SkMesh::IndexBuffer IndexBuffer
#define RETURN_ERROR(...)
static const char * varying_type_string(Varying::Type type)
ColorType get_fs_color_type(const SkSL::Program &fsProgram)
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
constexpr size_t SkToSizeT(S x)
static constexpr bool SkToBool(const T &x)
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< Base > Make(const void *data, size_t size)
SkSpan< const Uniform > uniforms() const
static constexpr size_t kStrideAlignment
const Uniform * findUniform(std::string_view name) const
static constexpr size_t kMaxVaryings
SkSpan< const Child > children() const
static constexpr size_t kMaxAttributes
static constexpr size_t kOffsetAlignment
static constexpr size_t kMaxStride
static Result Make(SkSpan< const Attribute > attributes, size_t vertexStride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs)
SkSpan< const Attribute > attributes() const
size_t uniformSize() const
const Varying * findVarying(std::string_view name) const
SkRuntimeEffect::Uniform Uniform
SkRuntimeEffect::Child Child
const Attribute * findAttribute(std::string_view name) const
const Child * findChild(std::string_view name) const
bool update(GrDirectContext *, const void *data, size_t offset, size_t size)
virtual size_t size() const =0
virtual bool onUpdate(GrDirectContext *, const void *data, size_t offset, size_t size)=0
bool update(GrDirectContext *, const void *data, size_t offset, size_t size)
SkMesh & operator=(const SkMesh &)
SkSpan< const ChildPtr > children() const
static Result Make(sk_sp< SkMeshSpecification >, Mode, sk_sp< VertexBuffer >, size_t vertexCount, size_t vertexOffset, sk_sp< const SkData > uniforms, SkSpan< ChildPtr > children, const SkRect &bounds)
size_t vertexCount() const
size_t vertexOffset() const
size_t indexCount() const
static Result MakeIndexed(sk_sp< SkMeshSpecification >, Mode, sk_sp< VertexBuffer >, size_t vertexCount, size_t vertexOffset, sk_sp< IndexBuffer >, size_t indexCount, size_t indexOffset, sk_sp< const SkData > uniforms, SkSpan< ChildPtr > children, const SkRect &bounds)
size_t indexOffset() const
const SkData * uniforms() const
SkMeshSpecification * spec() const
static const char * ChildTypeToStr(SkRuntimeEffect::ChildType type)
static SkRuntimeEffect::Uniform VarAsUniform(const SkSL::Variable &, const SkSL::Context &, size_t *offset)
static SkRuntimeEffect::Child VarAsChild(const SkSL::Variable &var, int index)
const FunctionDeclaration & declaration() const
std::unique_ptr< Statement > & declaration()
bool visit(const Program &program)
const Type & type() const
const Type & type() const
virtual bool visitStatement(typename T::Statement &statement)
virtual bool visitExpression(typename T::Expression &expression)
virtual bool visitProgramElement(typename T::ProgramElement &programElement)
bool matches(const Type &other) const
size_t add(size_t x, size_t y)
size_t mul(size_t x, size_t y)
constexpr bool empty() const
constexpr size_t size() const
void append(const char text[])
const char * c_str() const
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
static const char * begin(const StringSlice &s)
const uint8_t uint32_t uint32_t GError ** error
uint32_t Hash32(const void *data, size_t bytes, uint32_t seed)
SK_API sk_sp< SkMesh::IndexBuffer > CopyIndexBuffer(const sk_sp< SkMesh::IndexBuffer > &)
SK_API sk_sp< SkMesh::IndexBuffer > MakeIndexBuffer(const void *data, size_t size)
SK_API sk_sp< SkMesh::VertexBuffer > MakeVertexBuffer(const void *, size_t size)
SK_API sk_sp< SkMesh::VertexBuffer > CopyVertexBuffer(const sk_sp< SkMesh::VertexBuffer > &)
Optional< SkRect > bounds
bool CallsColorTransformIntrinsics(const Program &program)
Visitor(Ts...) -> Visitor< Ts... >
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
const myers::Point & get< 0 >(const myers::Segment &s)
SkMeshSpecification::ColorType ColorType
ElementsCollection elements() const
std::shared_ptr< Context > fContext
std::shared_ptr< const fml::Mapping > data