Flutter Engine
The Flutter Engine
Typedefs | Functions | Variables
MeshTest.cpp File Reference
#include "include/core/SkBlendMode.h"
#include "include/core/SkBlender.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkData.h"
#include "include/core/SkMesh.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkShader.h"
#include "include/core/SkSpan.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkRuntimeEffect.h"
#include "src/base/SkZip.h"
#include "src/core/SkMeshPriv.h"
#include "tests/Test.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <limits>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

Go to the source code of this file.

Typedefs

using Attribute = SkMeshSpecification::Attribute
 
using Varying = SkMeshSpecification::Varying
 

Functions

static const char * attr_type_str (const Attribute::Type type)
 
static const char * var_type_str (const Varying::Type type)
 
static SkString make_description (SkSpan< const Attribute > attributes, size_t stride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs)
 
static bool check_for_failure (skiatest::Reporter *reporter, SkSpan< const Attribute > attributes, size_t stride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs, const char *expectedErrorSubstring=nullptr)
 
static bool check_for_success (skiatest::Reporter *reporter, SkSpan< const Attribute > attributes, size_t stride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs, sk_sp< SkMeshSpecification > *spec=nullptr)
 
 DEF_TEST (MeshSpec_Valid, reporter)
 
 DEF_TEST (MeshSpec_InvalidSignature, reporter)
 
 DEF_TEST (MeshSpec_Float4Color, reporter)
 
 DEF_TEST (MeshSpec_DisallowsChildEffectInVertex, reporter)
 
 DEF_TEST (MeshSpec_AllowsChildEffectInFragment, reporter)
 
 DEF_TEST (MeshSpec_FindChild, reporter)
 
 DEF_TEST (Mesh_ChildEffectsMatchSpec, reporter)
 
 DEF_TEST (MeshSpec_ValidUniforms, reporter)
 
 DEF_TEST (MeshSpec_InvalidUniforms, reporter)
 
 DEF_TEST (MeshSpec_MissingMain, reporter)
 
 DEF_TEST (MeshSpec_ZeroAttributes, reporter)
 
 DEF_TEST (MeshSpec_ZeroVaryings, reporter)
 
 DEF_TEST (MeshSpec_InvalidStride, reporter)
 
 DEF_TEST (MeshSpec_InvalidOffset, reporter)
 
 DEF_TEST (MeshSpec_TooManyAttributes, reporter)
 
 DEF_TEST (MeshSpec_TooManyVaryings, reporter)
 
 DEF_TEST (MeshSpec_DuplicateAttributeNames, reporter)
 
 DEF_TEST (MeshSpec_DuplicateVaryingNames, reporter)
 
 DEF_TEST (MeshSpec_SneakyExtraAttribute, reporter)
 
 DEF_TEST (MeshSpec_SneakyExtraVarying, reporter)
 
 DEF_TEST (MeshSpec_AllowsFloat2PositionVarying, reporter)
 
 DEF_TEST (MeshSpec_InvalidPositionType, reporter)
 
 DEF_TEST (MeshSpec_EmptyAttributeName, reporter)
 
 DEF_TEST (MeshSpec_EmptyVaryingName, reporter)
 
 DEF_TEST (MeshSpecVaryingPassthrough, reporter)
 
 DEF_TEST (MeshSpecUnusedVaryings, reporter)
 

Variables

static const SkString kValidVS
 
static const SkString kValidFSes []
 
static const Attribute kValidAttrs []
 
static constexpr size_t kValidStride = 4*4
 
static const Varying kValidVaryings []
 
static constexpr const char * kSneakyName = "name; float3 sneaky"
 

Typedef Documentation

◆ Attribute

Definition at line 36 of file MeshTest.cpp.

◆ Varying

Definition at line 37 of file MeshTest.cpp.

Function Documentation

◆ attr_type_str()

static const char * attr_type_str ( const Attribute::Type  type)
static

Definition at line 39 of file MeshTest.cpp.

39 {
40 switch (type) {
41 case Attribute::Type::kFloat: return "float";
42 case Attribute::Type::kFloat2: return "float2";
43 case Attribute::Type::kFloat3: return "float3";
44 case Attribute::Type::kFloat4: return "float4";
45 case Attribute::Type::kUByte4_unorm: return "ubyte4_unorm";
46 }
48}
#define SkUNREACHABLE
Definition: SkAssert.h:135
GLenum type

◆ check_for_failure()

static bool check_for_failure ( skiatest::Reporter reporter,
SkSpan< const Attribute attributes,
size_t  stride,
SkSpan< const Varying varyings,
const SkString vs,
const SkString fs,
const char *  expectedErrorSubstring = nullptr 
)
static

Definition at line 94 of file MeshTest.cpp.

100 {
101 auto [spec, error] = SkMeshSpecification::Make(attributes, stride, varyings, vs, fs);
102 if (spec) {
104 "Expected to fail but succeeded:\n%s",
105 make_description(attributes, stride, varyings, vs, fs).c_str());
106 return false;
107 }
108 if (expectedErrorSubstring && !error.contains(expectedErrorSubstring)) {
110 " Expected: %s\n"
111 "Actual error: %s\n",
112 expectedErrorSubstring, error.c_str());
113 return false;
114 }
115 return true;
116}
reporter
Definition: FontMgrTest.cpp:39
static SkString make_description(SkSpan< const Attribute > attributes, size_t stride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs)
Definition: MeshTest.cpp:64
#define ERRORF(r,...)
Definition: Test.h:293
static Result Make(SkSpan< const Attribute > attributes, size_t vertexStride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs)
Definition: SkMesh.cpp:389
const uint8_t uint32_t uint32_t GError ** error

◆ check_for_success()

static bool check_for_success ( skiatest::Reporter reporter,
SkSpan< const Attribute attributes,
size_t  stride,
SkSpan< const Varying varyings,
const SkString vs,
const SkString fs,
sk_sp< SkMeshSpecification > *  spec = nullptr 
)
static

Definition at line 118 of file MeshTest.cpp.

124 {
125 auto [s, error] = SkMeshSpecification::Make(attributes, stride, varyings, vs, fs);
126 if (s) {
127 REPORTER_ASSERT(reporter, error.isEmpty());
128 if (spec) {
129 *spec = std::move(s);
130 }
131 return true;
132 }
134 "Expected to succeed but failed:\n%sError:\n%s",
135 make_description(attributes, stride, varyings, vs, fs).c_str(),
136 error.c_str());
137 return false;
138}
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
struct MyStruct s

◆ DEF_TEST() [1/26]

DEF_TEST ( Mesh_ChildEffectsMatchSpec  ,
reporter   
)

Definition at line 349 of file MeshTest.cpp.

353 {
354 auto test = [&](const char* prefix,
356 const char* expectedError = nullptr) {
357 SkString fsWithChild{prefix};
358 fsWithChild.append(kValidFSes[0]);
359
365 kValidVS,
366 fsWithChild,
367 &meshSpec)) {
368 return;
369 }
370
371 constexpr float kVertexCount = 4;
372 sk_sp<SkMesh::VertexBuffer> vertexBuffer =
376 vertexBuffer,
378 /*vertexOffset=*/0,
379 /*uniforms=*/nullptr,
380 children,
382
383 if (expectedError) {
384 REPORTER_ASSERT(reporter, !result.mesh.isValid());
386 result.error.contains(expectedError),
387 "Expected: '%s'\n"
388 " Actual: '%s'\n", expectedError, result.error.c_str());
389 } else {
390 REPORTER_ASSERT(reporter, result.mesh.isValid());
392 result.error.isEmpty(),
393 "Expected: no errors\n"
394 " Actual: '%s'\n", result.error.c_str());
395 }
396 };
397
401 SkRuntimeEffect::ChildPtr childNull[1] = {};
402
403 // These are expected to report a count mismatch.
404 test("uniform shader myshader;", {},
405 "The mesh specification declares 1 child effects, but the mesh supplies 0.");
406 test("", childShader,
407 "The mesh specification declares 0 child effects, but the mesh supplies 1.");
408
409 // These are expected to report a type mismatch.
410 test("uniform shader myshader;", childFilter,
411 "Child effect 'myshader' was specified as a shader, but passed as a color filter.");
412 test("uniform shader myshader;", childBlender,
413 "Child effect 'myshader' was specified as a shader, but passed as a blender.");
414 test("uniform colorFilter myfilter;", childShader,
415 "Child effect 'myfilter' was specified as a color filter, but passed as a shader.");
416 test("uniform colorFilter myfilter;", childBlender,
417 "Child effect 'myfilter' was specified as a color filter, but passed as a blender.");
418 test("uniform blender myblender;", childShader,
419 "Child effect 'myblender' was specified as a blender, but passed as a shader.");
420 test("uniform blender myblender;", childFilter,
421 "Child effect 'myblender' was specified as a blender, but passed as a color filter.");
422
423 // Null children are supported.
424 test("uniform shader myshader;", childNull);
425 test("uniform shader myfilter;", childNull);
426 test("uniform shader myblender;", childNull);
427
428 // Properly-typed child effects are supported.
429 test("uniform shader myshader;", childShader);
#define test(name)
static const size_t kVertexCount
static const Attribute kValidAttrs[]
Definition: MeshTest.cpp:159
static const SkString kValidFSes[]
Definition: MeshTest.cpp:148
static bool check_for_success(skiatest::Reporter *reporter, SkSpan< const Attribute > attributes, size_t stride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs, sk_sp< SkMeshSpecification > *spec=nullptr)
Definition: MeshTest.cpp:118
static const SkString kValidVS
Definition: MeshTest.cpp:141
static const Varying kValidVaryings[]
Definition: MeshTest.cpp:163
static constexpr size_t kValidStride
Definition: MeshTest.cpp:162
@ kSrcOver
r = s + (1-sa)*d
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
static sk_sp< SkBlender > Mode(SkBlendMode mode)
static sk_sp< SkColorFilter > LinearToSRGBGamma()
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)
Definition: SkMesh.cpp:694
GAsyncResult * result
SK_API sk_sp< SkMesh::VertexBuffer > MakeVertexBuffer(const void *, size_t size)
Definition: SkMesh.cpp:905
SK_API sk_sp< SkShader > Color(SkColor)
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595

◆ DEF_TEST() [2/26]

DEF_TEST ( MeshSpec_AllowsChildEffectInFragment  ,
reporter   
)

Definition at line 304 of file MeshTest.cpp.

308 {
309 static constexpr const char* kChildEffects[] {
310 "uniform shader myshader;",
311 "uniform colorFilter mycolorfilter; uniform shader myshader;",
312 "uniform shader myshader; uniform blender myblender; uniform colorFilter mycolorfilter;"
313 };
314
315 for (const auto& global : kChildEffects) {
316 SkString fsWithChild{global};
317 fsWithChild.append(kValidFSes[0]);
318
323 kValidVS,
324 fsWithChild)) {
void append(const char text[])
Definition: SkString.h:203

◆ DEF_TEST() [3/26]

DEF_TEST ( MeshSpec_AllowsFloat2PositionVarying  ,
reporter   
)

Definition at line 921 of file MeshTest.cpp.

925 {
926 // Position varying can be explicit if it is float2
927 static const Varying kVaryings[] {
928 {Varying::Type::kFloat2, SkString{"position"}},
929 };

◆ DEF_TEST() [4/26]

DEF_TEST ( MeshSpec_DisallowsChildEffectInVertex  ,
reporter   
)

Definition at line 268 of file MeshTest.cpp.

272 {
273 static constexpr const char* kChildEffects[] {
274 "uniform shader myshader;",
275 "uniform colorFilter mycolorfilter;",
276 "uniform blender myblender;"
277 };
278
279 for (const auto& global : kChildEffects) {
280 SkString vsWithChild{global};
281 vsWithChild.append(kValidVS);
282
283 SkString fsWithChild{global};
284 fsWithChild.append(kValidFSes[0]);
285
290 vsWithChild,
291 kValidFSes[0],
292 "effects are not permitted in mesh vertex shaders")) {
293 return;
294 }
295
300 vsWithChild,
301 fsWithChild,
302 "effects are not permitted in mesh vertex shaders")) {
static bool check_for_failure(skiatest::Reporter *reporter, SkSpan< const Attribute > attributes, size_t stride, SkSpan< const Varying > varyings, const SkString &vs, const SkString &fs, const char *expectedErrorSubstring=nullptr)
Definition: MeshTest.cpp:94

◆ DEF_TEST() [5/26]

DEF_TEST ( MeshSpec_DuplicateAttributeNames  ,
reporter   
)

Definition at line 869 of file MeshTest.cpp.

873 {
874 static const Attribute kAttributes[] {
877 };
880 24,
static const std::map< std::string, VerticesBuilder::AttributeType > kAttributes

◆ DEF_TEST() [6/26]

DEF_TEST ( MeshSpec_DuplicateVaryingNames  ,
reporter   
)

Definition at line 882 of file MeshTest.cpp.

◆ DEF_TEST() [7/26]

DEF_TEST ( MeshSpec_EmptyAttributeName  ,
reporter   
)

Definition at line 947 of file MeshTest.cpp.

951 {
952 static const Attribute kAttributes[] {
954 };
957 16,

◆ DEF_TEST() [8/26]

DEF_TEST ( MeshSpec_EmptyVaryingName  ,
reporter   
)

Definition at line 959 of file MeshTest.cpp.

963 {
964 static const Varying kVaryings[] {
966 };

◆ DEF_TEST() [9/26]

DEF_TEST ( MeshSpec_FindChild  ,
reporter   
)

Definition at line 326 of file MeshTest.cpp.

330 {
331 SkString fsWithChild{"uniform shader myshader;"
332 "uniform blender myblender;"
333 "uniform colorFilter mycolorfilter;"};
334 fsWithChild.append(kValidFSes[0]);
335
341 kValidVS,
342 fsWithChild,
343 &meshSpec)) {
344 return;
345 }
346
347 REPORTER_ASSERT(reporter, meshSpec->findChild("myshader")->index == 0);
const Child * findChild(std::string_view name) const
Definition: SkMesh.cpp:656

◆ DEF_TEST() [10/26]

DEF_TEST ( MeshSpec_Float4Color  ,
reporter   
)

Definition at line 256 of file MeshTest.cpp.

256 {
257 static const SkString kFloat4FS {
258 R"(
259 float2 main(const Varyings varyings, out float4 color) {
260 color = float4(.2); return float2(10);
261 }
262 )"
263 };

◆ DEF_TEST() [11/26]

DEF_TEST ( MeshSpec_InvalidOffset  ,
reporter   
)

Definition at line 796 of file MeshTest.cpp.

800 {
801 { // offset isn't aligned
802 static const Attribute kAttributes[] {
804 };
807 32,
809 kValidVS,
810 kValidFSes[0])) {
811 return;
812 }
813 }
814 { // straddles stride boundary
815 static const Attribute kAttributes[] {
818 };
821 20,
823 kValidVS,
824 kValidFSes[0])) {
825 return;
826 }
827 }
828 { // straddles stride boundary with attempt to overflow
829 static const Attribute kAttributes[] {
831 };
834 4,
836 kValidVS,
837 kValidFSes[0])) {
static float max(float r, float g, float b)
Definition: hsl.cpp:49

◆ DEF_TEST() [12/26]

DEF_TEST ( MeshSpec_InvalidPositionType  ,
reporter   
)

Definition at line 934 of file MeshTest.cpp.

938 {
939 // Position varying can be explicit but it must be float2
940 static const Varying kVaryings[] {
941 {Varying::Type::kFloat4, SkString{"position"}},
942 };

◆ DEF_TEST() [13/26]

DEF_TEST ( MeshSpec_InvalidSignature  ,
reporter   
)

Definition at line 180 of file MeshTest.cpp.

180 {
181 static constexpr const char* kVSBody = "{ return float2(10); }";
182
183 static constexpr const char* kInvalidVSSigs[] {
184 "float3 main(const Attributes attrs)", // bad return
185 "Varyings main(Attributes attrs)", // non-const Attributes
186 "Varyings main(out Attributes attrs)", // out Varyings
187 "Varyings main()", // no Attributes
188 "Varyings main(const Varyings v, float2)" // extra arg
189 };
190
191 static constexpr const char* kNoColorFSBody = "{ return float2(10); }";
192
193 static constexpr const char* kInvalidNoColorFSSigs[] {
194 "half2 main(const Varyings v)", // bad return
195 "float2 main(const Attributes v)", // wrong param type
196 "float2 main(inout Varyings attrs)", // inout Varyings
197 "float2 main(Varyings v)", // non-const Varyings
198 "float2 main()", // no args
199 "float2 main(const Varyings, float)" // extra arg
200 };
201
202 static constexpr const char* kColorFSBody = "{ color = half4(.2); return float2(10); }";
203
204 static constexpr const char* kInvalidColorFSSigs[] {
205 "half2 main(const Varyings v, out half4 color)", // bad return
206 "float2 main(const Attributes v, out half4 color)", // wrong first param type
207 "float2 main(const Varyings v, out half3 color)", // wrong second param type
208 "float2 main(out Varyings v, out half4 color)", // out Varyings
209 "float2 main(const Varyings v, half4 color)", // in color
210 "float2 main(const Varyings v, out half4 color, float)" // extra arg
211 };
212
213 for (const char* vsSig : kInvalidVSSigs) {
214 SkString invalidVS;
215 invalidVS.appendf("%s %s", vsSig, kVSBody);
216 for (const auto& validFS : kValidFSes) {
221 invalidVS,
222 validFS)) {
223 return;
224 }
225 }
226 }
227
228 for (const char* noColorFSSig : kInvalidNoColorFSSigs) {
229 SkString invalidFS;
230 invalidFS.appendf("%s %s", noColorFSSig, kNoColorFSBody);
235 kValidVS,
236 invalidFS)) {
237 return;
238 }
239 }
240
241 for (const char* colorFSSig : kInvalidColorFSSigs) {
242 SkString invalidFS;
243 invalidFS.appendf("%s %s", colorFSSig, kColorFSBody);
248 kValidVS,
249 invalidFS)) {
250 return;
251 }
252 }
253}
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550

◆ DEF_TEST() [14/26]

DEF_TEST ( MeshSpec_InvalidStride  ,
reporter   
)

Definition at line 764 of file MeshTest.cpp.

768 {
769 // Zero stride
772 0,
774 kValidVS,
775 kValidFSes[0])) {
776 return;
777 }
778
779 // Unaligned
782 kValidStride + 1,
784 kValidVS,
785 kValidFSes[0])) {
786 return;
787 }
788
789 // Too large
792 1 << 20,
794 kValidVS,

◆ DEF_TEST() [15/26]

DEF_TEST ( MeshSpec_InvalidUniforms  ,
reporter   
)

Definition at line 661 of file MeshTest.cpp.

665 {
666 // We assume general uniform declarations are broadly tested generically in SkSL. Here we are
667 // concerned with agreement between VS and FS declarations, which is a unique aspect of
668 // SkMeshSpecification.
669
670 // Each test case is a fs and vs uniform declaration with the same name but some other
671 // difference that should make them incompatible.
672 static std::tuple<const char*, const char*> kTestCases[]{
673 // different types
674 {"uniform float x;", "uniform int x;"},
675 // array vs non-array
676 {"uniform float2x2 m[1];", "uniform float2x2 m;"},
677 // array count mismatch
678 {"uniform int3 i[1];", "uniform int3 i[2];"},
679 // layout difference
680 {"layout(color) uniform float4 color;", "uniform float4 color;"},
681 };
682
683 for (bool reverse : {false, true}) {
684 for (auto [u1, u2] : kTestCases) {
685 if (reverse) {
686 using std::swap;
687 swap(u1, u2);
688 }
689 SkString vs = kValidVS;
690 vs.prepend(u1);
691
692 SkString fs = kValidFSes[0];
693 fs.prepend(u2);
694
695 auto attrs = SkSpan(kValidAttrs);
696 auto varys = SkSpan(kValidVaryings);
697 if (!check_for_failure(reporter, attrs, kValidStride, varys, vs, fs)) {
698 return;
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
void prepend(const char text[])
Definition: SkString.h:215

◆ DEF_TEST() [16/26]

DEF_TEST ( MeshSpec_MissingMain  ,
reporter   
)

Definition at line 700 of file MeshTest.cpp.

704 {
705 static const SkString kHelper{"float2 swiz(float2 x) { return z.yx; }"};
706
707 // Empty VS
712 SkString{},
713 kValidFSes[0])) {
714 return;
715 }
716
717 // VS with helper function but no main
722 kHelper,
723 kValidFSes[0])) {
724 return;
725 }
726
727 // Empty FS
732 kValidVS,
733 SkString{})) {
734 return;
735 }
736
737 // VS with helper function but no main
742 kValidVS,

◆ DEF_TEST() [17/26]

DEF_TEST ( MeshSpec_SneakyExtraAttribute  ,
reporter   
)

Definition at line 897 of file MeshTest.cpp.

901 {
902 static const Attribute kAttributes[] {
904 };
907 16,
static constexpr const char * kSneakyName
Definition: MeshTest.cpp:895

◆ DEF_TEST() [18/26]

DEF_TEST ( MeshSpec_SneakyExtraVarying  ,
reporter   
)

Definition at line 909 of file MeshTest.cpp.

913 {
914 static const Varying kVaryings[] {
916 };

◆ DEF_TEST() [19/26]

DEF_TEST ( MeshSpec_TooManyAttributes  ,
reporter   
)

Definition at line 839 of file MeshTest.cpp.

843 {
844 static constexpr size_t kN = 500;
845 std::vector<Attribute> attrs;
846 attrs.reserve(kN);
847 for (size_t i = 0; i < kN; ++i) {
848 attrs.push_back({Attribute::Type::kFloat4, 0, SkStringPrintf("attr%zu", i)});
849 }
851 attrs,
852 4*4,
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.

◆ DEF_TEST() [20/26]

DEF_TEST ( MeshSpec_TooManyVaryings  ,
reporter   
)

Definition at line 854 of file MeshTest.cpp.

858 {
859 static constexpr size_t kN = 500;
860 std::vector<Varying> varyings;
861 varyings.reserve(kN);
862 for (size_t i = 0; i < kN; ++i) {
863 varyings.push_back({Varying::Type::kFloat4, SkStringPrintf("varying%zu", i)});
864 }

◆ DEF_TEST() [21/26]

DEF_TEST ( MeshSpec_Valid  ,
reporter   
)

Definition at line 167 of file MeshTest.cpp.

167 {
168 for (const auto& validFS : kValidFSes) {
173 kValidVS,
174 validFS)) {
175 return;
176 }
177 }
178}

◆ DEF_TEST() [22/26]

DEF_TEST ( MeshSpec_ValidUniforms  ,
reporter   
)

Definition at line 431 of file MeshTest.cpp.

435 {
437 using Type = Uniform::Type;
438 using Flags = Uniform::Flags;
439
440 constexpr Flags kVS = Uniform::kVertex_Flag;
441 constexpr Flags kFS = Uniform::kFragment_Flag;
443 constexpr Flags kHalfP = Uniform::kHalfPrecision_Flag;
444
445 auto make_uni = [](Type type,
446 std::string_view name,
447 size_t offset,
448 uint32_t flags,
449 int count = 0) {
450 if (count) {
452 } else {
454 return Uniform{name, offset, type, 1, flags};
455 }
456 };
457
458 // Each test case is a set of VS and FS uniform declarations followed and the expected output
459 // of SkMeshSpecification::uniforms().
460 struct {
461 const std::vector<const char*> vsUniformDecls;
462 const std::vector<const char*> fsUniformDecls;
463 const std::vector<SkMeshSpecification::Uniform> expectations;
464 } static kTestCases[] {
465 // A single VS uniform.
466 {
467 {
468 "uniform float x;"
469 },
470 {},
471 {
472 make_uni(Type::kFloat, "x", 0, kVS)
473 }
474 },
475
476 // A single FS uniform.
477 {
478 {},
479 {
480 "uniform float2 v;"
481 },
482 {
483 make_uni(Type::kFloat2, "v", 0, kFS)
484 }
485 },
486
487 // A single uniform in both that uses color layout.
488 {
489 {
490 "layout(color) uniform float4 color;",
491 },
492 {
493 "layout(color) uniform float4 color;",
494 },
495 {
496 make_uni(Type::kFloat4, "color", 0, kVS|kFS|kColor)
497 }
498 },
499
500 // A shared uniform after an unshared vertex uniform
501 {
502 {
503 "layout(color) uniform float4 color;",
504 " uniform float x[5];",
505 },
506 {
507 "uniform float x[5];",
508 },
509 {
510 make_uni(Type::kFloat4, "color", 0, kVS|kColor, 0),
511 make_uni(Type::kFloat , "x" , 16, kVS|kFS , 5)
512 }
513 },
514
515 // A shared uniform before an unshared vertex uniform
516 {
517 {
518 "uniform half x[2];",
519 "uniform int y;",
520 },
521 {
522 "uniform half x[2];",
523 },
524 {
525 make_uni(Type::kFloat, "x", 0, kVS|kFS|kHalfP, 2),
526 make_uni(Type::kInt, "y", 8, kVS , 0)
527 }
528 },
529
530 // A shared uniform after an unshared fragment uniform
531 {
532 {
533 "uniform float3x3 m;",
534 },
535 {
536 "uniform int2 i2;",
537 "uniform float3x3 m;",
538 },
539 {
540 make_uni(Type::kFloat3x3, "m" , 0, kVS|kFS),
541 make_uni(Type::kInt2 , "i2", 36, kFS )
542 }
543 },
544
545 // A shared uniform before an unshared fragment uniform
546 {
547 {
548 "uniform half4x4 m[4];",
549 },
550 {
551 "uniform half4x4 m[4];",
552 "uniform int3 i3[1];",
553 },
554 {
555 make_uni(Type::kFloat4x4, "m", 0, kVS|kFS|kHalfP, 4),
556 make_uni(Type::kInt3, "i3", 256, kFS , 1)
557 }
558 },
559
560 // Complex case with 2 shared uniforms that are declared in the opposite order.
561 {
562 {
563 "uniform float x;"
564 "uniform half4x4 m[4];", // shared
565 "uniform int2 i2[2];"
566 "uniform float3 v[8];" // shared
567 "uniform int3 i3;"
568 },
569 {
570 "uniform float y;"
571 "uniform float3 v[8];" // shared
572 "uniform int4 i4[2];"
573 "uniform half4x4 m[4];", // shared
574 "uniform int i;"
575 },
576 {
577 make_uni(Type::kFloat, "x" , 0, kVS , 0),
578 make_uni(Type::kFloat4x4, "m" , 4, kVS|kFS|kHalfP, 4),
579 make_uni(Type::kInt2, "i2", 260, kVS , 2),
580 make_uni(Type::kFloat3, "v" , 276, kVS|kFS , 8),
581 make_uni(Type::kInt3, "i3", 372, kVS , 0),
582 make_uni(Type::kFloat, "y" , 384, kFS , 0),
583 make_uni(Type::kInt4, "i4", 388, kFS , 2),
584 make_uni(Type::kInt, "i" , 420, kFS , 0),
585 }
586 },
587 };
588
589 for (const auto& c : kTestCases) {
590 SkString vs = kValidVS;
591 SkString unis;
592 for (const auto u : c.vsUniformDecls) {
593 unis.append(u);
594 }
595 vs.prepend(unis);
596
597 SkString fs = kValidFSes[0];
598 unis = {};
599 for (const auto u : c.fsUniformDecls) {
600 unis.append(u);
601 }
602 fs.prepend(unis);
603
604 auto attrs = SkSpan(kValidAttrs);
605 auto varys = SkSpan(kValidVaryings);
607 if (!check_for_success(reporter, attrs, kValidStride, varys, vs, fs, &spec)) {
608 return;
609 }
610 SkString desc = make_description(attrs, kValidStride, varys, vs, fs);
611 SkSpan<const Uniform> uniforms = spec->uniforms();
612 if (uniforms.size() != c.expectations.size()) {
614 "Expected %zu uniforms but actually %zu:\n%s",
615 c.expectations.size(),
616 uniforms.size(),
617 desc.c_str());
618 return;
619 }
620 for (const auto& [actual, expected] : SkMakeZip(uniforms, c.expectations)) {
621 std::string name = std::string(actual.name);
622 if (name != expected.name) {
624 "Actual uniform name (%s) does not match expected name (%.*s)",
625 name.c_str(),
626 (int)expected.name.size(), expected.name.data());
627 return;
628 }
629 if (actual.type != expected.type) {
631 "Uniform %s: Actual type (%d) does not match expected type (%d)",
632 name.c_str(),
633 static_cast<int>(actual.type),
634 static_cast<int>(expected.type));
635 return;
636 }
637 if (actual.count != expected.count) {
639 "Uniform %s: Actual count (%d) does not match expected count (%d)",
640 name.c_str(),
641 actual.count,
642 expected.count);
643 return;
644 }
645 if (actual.flags != expected.flags) {
647 "Uniform %s: Actual flags (0x%04x) do not match expected flags (0x%04x)",
648 name.c_str(),
649 actual.flags,
650 expected.flags);
651 return;
652 }
653 if (actual.offset != expected.offset) {
655 "Uniform %s: Actual offset (%zu) does not match expected offset (%zu)",
656 name.c_str(),
657 actual.offset,
658 expected.offset);
659 return;
static constexpr SkColor kColor
Definition: CanvasTest.cpp:265
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr auto SkMakeZip(Ts &&... ts)
Definition: SkZip.h:212
SkSpan< const Uniform > uniforms() const
Definition: SkMesh.h:170
SkRuntimeEffect::Uniform Uniform
Definition: SkMesh.h:106
constexpr size_t size() const
Definition: SkSpan_impl.h:95
FlutterSemanticsFlag flags
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
SeparatedVector2 offset

◆ DEF_TEST() [23/26]

DEF_TEST ( MeshSpec_ZeroAttributes  ,
reporter   
)

Definition at line 744 of file MeshTest.cpp.

748 {
749 // We require at least one attribute

◆ DEF_TEST() [24/26]

DEF_TEST ( MeshSpec_ZeroVaryings  ,
reporter   
)

Definition at line 754 of file MeshTest.cpp.

758 {
759 // Varyings are not required.

◆ DEF_TEST() [25/26]

DEF_TEST ( MeshSpecUnusedVaryings  ,
reporter   
)

Definition at line 1087 of file MeshTest.cpp.

1091 {
1092 static const Attribute kAttributes[]{
1093 {Attribute::Type::kFloat2, 0, SkString{"position"}},
1096 };
1097 static const Varying kVaryings[]{
1098 {Varying::Type::kFloat2, SkString{"position"}},
1100 {Varying::Type::kHalf4, SkString{"color"} },
1101 };
1102
1103 static constexpr char kVS[] = R"(
1104 Varyings main(const Attributes a) {
1105 Varyings v;
1106 v.uv = a.uv;
1107 v.position = a.position;
1108 v.color = a.color;
1109 return v;
1110 }
1111 )";
1112
1113 auto check = [&](const char* fs, bool positionDead, bool uvDead, bool colorDead) {
1114 static_assert(std::size(kVaryings) == 3);
1116 /*vertexStride=*/24,
1117 kVaryings,
1118 SkString(kVS),
1119 SkString(fs));
1120 if (!spec) {
1121 ERRORF(reporter, "%s\n%s", fs, error.c_str());
1122 return;
1123 }
1124 bool positionActuallyDead = SkMeshSpecificationPriv::VaryingIsDead(*spec, 0);
1125 bool uvActuallyDead = SkMeshSpecificationPriv::VaryingIsDead(*spec, 1);
1126 bool colorActuallyDead = SkMeshSpecificationPriv::VaryingIsDead(*spec, 2);
1127 auto str = [](bool dead) { return dead ? "dead" : "not dead"; };
1128 if (positionActuallyDead != positionDead) {
1130 "Expected position to be detected %s but it is detected %s.\n%s",
1131 str(positionDead),
1132 str(positionActuallyDead),
1133 fs);
1134 }
1135 if (uvActuallyDead != uvDead) {
1137 "Expected uv to be detected %s but it is detected %s.\n%s",
1138 str(uvDead),
1139 str(uvActuallyDead),
1140 fs);
1141 }
1142 if (colorActuallyDead != colorDead) {
1144 "Expected color to be detected %s but it is detected %s.\n%s",
1145 str(colorDead),
1146 str(colorActuallyDead),
1147 fs);
1148 }
1149 };
1150
1151 // Simple
1152 check(R"(float2 main(const Varyings v) {
1153 return v.uv;
1154 })",
1155 true,
1156 true,
1157 true);
1158
1159 // Simple, using position
1160 check(R"(float2 main(const Varyings v) {
1161 return v.position;
1162 })",
1163 true,
1164 true,
1165 true);
1166
1167 // Two returns that are both passthrough of the same varying
1168 check(R"(float2 main(const Varyings v, out half4 color) {
1169 if (v.color.r > 0.5) {
1170 color = v.color;
1171 return v.uv;
1172 } else {
1173 color = 2*color;
1174 return v.uv;
1175 }
1176 })",
1177 true,
1178 true,
1179 false);
1180
1181 // Two returns that are both passthrough of the different varyings and unused other varying
1182 check(R"(float2 main(const Varyings v, out half4 color) {
1183 if (v.position.x > 10) {
1184 color = half4(0);
1185 return v.uv;
1186 } else {
1187 color = half4(1);
1188 return v.position;
1189 }
1190 })",
1191 false,
1192 false,
1193 true);
1194
1195 // Passthrough but we also use the varying elsewhere
1196 check(R"(float2 main(const Varyings v, out half4 color) {
1197 color = half4(v.uv.x, 0, 0, 1);
1198 return v.uv;
1199 })",
1200 true,
1201 false,
1202 true);
1203
1204 // Use two varyings is a return statement
1205 check(R"(float2 main(const Varyings v) {
1206 return v.uv + v.position;
1207 })",
1208 false,
1209 false,
1210 true);
1211
1212 // Slightly more complicated varying use.
1213 check(R"(noinline vec2 get_pos(const Varyings v) { return v.position; }
1214
1215 noinline half4 identity(half4 c) { return c; }
1216
1217 float2 main(const Varyings v, out half4 color) {
1218 color = identity(v.color);
1219 return v.uv + get_pos(v);
1220 })",
1221 false,
1222 false,
1223 false);
1224
1225 // Go through assignment to another Varyings.
1226 check(R"(float2 main(const Varyings v) {
1227 Varyings otherVaryings;
1228 otherVaryings = v;
1229 return otherVaryings.uv;
1230 })",
1231 true,
1232 false,
1233 true);
1234
1235 // We're not very smart. We just look for any use of the field in any Varyings value and don't
1236 // do any data flow analysis.
1237 check(R"(float2 main(const Varyings v) {
1238 Varyings otherVaryings;
1239 otherVaryings.uv = half2(5);
1240 otherVaryings.position = half2(10);
1241 return otherVaryings.position;
1242 })",
#define check(reporter, ref, unref, make, kill)
Definition: RefCntTest.cpp:85
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
Definition: switches.h:259
static bool VaryingIsDead(const SkMeshSpecification &spec, int v)
Definition: SkMeshPriv.h:75

◆ DEF_TEST() [26/26]

DEF_TEST ( MeshSpecVaryingPassthrough  ,
reporter   
)

Definition at line 971 of file MeshTest.cpp.

975 {
976 static const Attribute kAttributes[]{
977 {Attribute::Type::kFloat2, 0, SkString{"position"}},
980 };
981 static const Varying kVaryings[]{
982 {Varying::Type::kFloat2, SkString{"position"}},
984 {Varying::Type::kHalf4, SkString{"color"} },
985 };
986
987 static constexpr char kVS[] = R"(
988 Varyings main(const Attributes a) {
989 Varyings v;
990 v.uv = a.uv;
991 v.position = a.position;
992 v.color = a.color;
993 return v;
994 }
995 )";
996 auto check = [&] (const char* fs, const char* passthroughAttr) {
998 /*vertexStride=*/24,
999 kVaryings,
1000 SkString(kVS),
1001 SkString(fs));
1002 if (!spec) {
1003 ERRORF(reporter, "%s\n%s", fs, error.c_str());
1004 return;
1005 }
1007 const SkString& actualAttr = idx >= 0 ? spec->attributes()[idx].name : SkString("<none>");
1008 if (!passthroughAttr) {
1009 if (idx >= 0) {
1010 ERRORF(reporter, "Expected no passthrough coords attribute, found %s.\n%s",
1011 actualAttr.c_str(),
1012 fs);
1013 }
1014 } else if (!actualAttr.equals(passthroughAttr)) {
1015 ERRORF(reporter, "Expected %s as passthrough coords attribute, found %s.\n%s",
1016 passthroughAttr,
1017 actualAttr.c_str(),
1018 fs);
1019 }
1020 };
1021
1022 // Simple
1023 check(R"(float2 main(const Varyings v) {
1024 return v.uv;
1025 })",
1026 "uv");
1027
1028 // Simple, using position
1029 check(R"(float2 main(const Varyings v) {
1030 return v.position;
1031 })",
1032 "position");
1033
1034 // Simple, with output color
1035 check(R"(float2 main(const Varyings v, out half4 color) {
1036 color = v.color;
1037 return v.uv;
1038 })",
1039 "uv");
1040
1041 // Three returns, all the same.
1042 check(R"(uniform int selector;
1043
1044 float2 main(const Varyings v, out half4 color) {
1045 if (selector == 0) {
1046 color = half4(1, 0, 0, 1);
1047 return v.position;
1048 }
1049 if (selector == 1) {
1050 color = half4(1, 1, 0, 1);
1051 return v.position;
1052 }
1053 color = half4(1, 0, 1, 1);
1054 return v.position;
1055 })",
1056 "position");
1057
1058 // Three returns, one not like the others
1059 check(R"(uniform int selector;
1060
1061 float2 main(const Varyings v, out half4 color) {
1062 if (selector == 0) {
1063 color = color.bgra;
1064 return v.position;
1065 }
1066 if (selector == 1) {
1067 color = half4(1);
1068 return v.uv;
1069 }
1070 color = color;
1071 return v.position;
1072 })",
1073 nullptr);
1074
1075 // Swizzles aren't handled (yet?).
1076 check(R"(float2 main(const Varyings v) {
1077 return v.uv.yx;
1078 })",
1079 nullptr);
1080
1081 // Return from non-main fools us?
1082 check(R"(noinline half4 get_color(const Varyings v) { return v.color; }
1083
1084 float2 main(const Varyings v, out half4 color) {
1085 color = get_color(v);
bool equals(const SkString &) const
Definition: SkString.cpp:324
const char * c_str() const
Definition: SkString.h:133
static int PassthroughLocalCoordsVaryingIndex(const SkMeshSpecification &spec)
Definition: SkMeshPriv.h:65

◆ make_description()

static SkString make_description ( SkSpan< const Attribute attributes,
size_t  stride,
SkSpan< const Varying varyings,
const SkString vs,
const SkString fs 
)
static

Definition at line 64 of file MeshTest.cpp.

68 {
69 static constexpr size_t kMax = 10;
71 result.appendf("Attributes (count=%zu, stride=%zu):\n", attributes.size(), stride);
72 for (size_t i = 0; i < std::min(kMax, attributes.size()); ++i) {
73 const auto& a = attributes[i];
74 result.appendf(" {%-10s, %3zu, \"%s\"}\n", attr_type_str(a.type), a.offset, a.name.c_str());
75 }
76 if (kMax < attributes.size()) {
77 result.append(" ...\n");
78 }
79
80 result.appendf("Varyings (count=%zu):\n", varyings.size());
81 for (size_t i = 0; i < std::min(kMax, varyings.size()); ++i) {
82 const auto& v = varyings[i];
83 result.appendf(" {%5s, \"%s\"}\n", var_type_str(v.type), v.name.c_str());
84 }
85 if (kMax < varyings.size()) {
86 result.append(" ...\n");
87 }
88
89 result.appendf("\n--VS--\n%s\n------\n", vs.c_str());
90 result.appendf("\n--FS--\n%s\n------\n", fs.c_str());
91 return result;
92}
static const char * attr_type_str(const Attribute::Type type)
Definition: MeshTest.cpp:39
static const char * var_type_str(const Varying::Type type)
Definition: MeshTest.cpp:50
struct MyStruct a[10]
static float min(float r, float g, float b)
Definition: hsl.cpp:48

◆ var_type_str()

static const char * var_type_str ( const Varying::Type  type)
static

Definition at line 50 of file MeshTest.cpp.

50 {
51 switch (type) {
52 case Varying::Type::kFloat: return "float";
53 case Varying::Type::kFloat2: return "float2";
54 case Varying::Type::kFloat3: return "float3";
55 case Varying::Type::kFloat4: return "float4";
56 case Varying::Type::kHalf: return "half";
57 case Varying::Type::kHalf2: return "half2";
58 case Varying::Type::kHalf3: return "half3";
59 case Varying::Type::kHalf4: return "half4";
60 }
62}

Variable Documentation

◆ kSneakyName

constexpr const char* kSneakyName = "name; float3 sneaky"
staticconstexpr

Definition at line 895 of file MeshTest.cpp.

◆ kValidAttrs

const Attribute kValidAttrs[]
static
Initial value:
= {
}

Definition at line 159 of file MeshTest.cpp.

◆ kValidFSes

const SkString kValidFSes[]
static
Initial value:
{
SkString{"float2 main(const Varyings varyings) { return float2(10); }"},
float2 main(const Varyings varyings, out half4 color) {
color = half4(.2);
return float2(10);
}
)"},
}

Definition at line 148 of file MeshTest.cpp.

◆ kValidStride

constexpr size_t kValidStride = 4*4
staticconstexpr

Definition at line 162 of file MeshTest.cpp.

◆ kValidVaryings

const Varying kValidVaryings[]
static
Initial value:

Definition at line 163 of file MeshTest.cpp.

◆ kValidVS

const SkString kValidVS
static
Initial value:
{R"(
Varyings main(const Attributes attrs) {
Varyings v;
return v;
})"}

Definition at line 141 of file MeshTest.cpp.