1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google LLC
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 #include "include/core/SkBlendMode.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlender.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMesh.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkRuntimeEffect.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkZip.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMeshPriv.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
26*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
27*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
28*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
29*c8dee2aaSAndroid Build Coastguard Worker #include <limits>
30*c8dee2aaSAndroid Build Coastguard Worker #include <string>
31*c8dee2aaSAndroid Build Coastguard Worker #include <string_view>
32*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
33*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
34*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker using Attribute = SkMeshSpecification::Attribute;
37*c8dee2aaSAndroid Build Coastguard Worker using Varying = SkMeshSpecification::Varying;
38*c8dee2aaSAndroid Build Coastguard Worker
attr_type_str(const Attribute::Type type)39*c8dee2aaSAndroid Build Coastguard Worker static const char* attr_type_str(const Attribute::Type type) {
40*c8dee2aaSAndroid Build Coastguard Worker switch (type) {
41*c8dee2aaSAndroid Build Coastguard Worker case Attribute::Type::kFloat: return "float";
42*c8dee2aaSAndroid Build Coastguard Worker case Attribute::Type::kFloat2: return "float2";
43*c8dee2aaSAndroid Build Coastguard Worker case Attribute::Type::kFloat3: return "float3";
44*c8dee2aaSAndroid Build Coastguard Worker case Attribute::Type::kFloat4: return "float4";
45*c8dee2aaSAndroid Build Coastguard Worker case Attribute::Type::kUByte4_unorm: return "ubyte4_unorm";
46*c8dee2aaSAndroid Build Coastguard Worker }
47*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
48*c8dee2aaSAndroid Build Coastguard Worker }
49*c8dee2aaSAndroid Build Coastguard Worker
var_type_str(const Varying::Type type)50*c8dee2aaSAndroid Build Coastguard Worker static const char* var_type_str(const Varying::Type type) {
51*c8dee2aaSAndroid Build Coastguard Worker switch (type) {
52*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kFloat: return "float";
53*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kFloat2: return "float2";
54*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kFloat3: return "float3";
55*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kFloat4: return "float4";
56*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kHalf: return "half";
57*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kHalf2: return "half2";
58*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kHalf3: return "half3";
59*c8dee2aaSAndroid Build Coastguard Worker case Varying::Type::kHalf4: return "half4";
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
62*c8dee2aaSAndroid Build Coastguard Worker }
63*c8dee2aaSAndroid Build Coastguard Worker
make_description(SkSpan<const Attribute> attributes,size_t stride,SkSpan<const Varying> varyings,const SkString & vs,const SkString & fs)64*c8dee2aaSAndroid Build Coastguard Worker static SkString make_description(SkSpan<const Attribute> attributes,
65*c8dee2aaSAndroid Build Coastguard Worker size_t stride,
66*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Varying> varyings,
67*c8dee2aaSAndroid Build Coastguard Worker const SkString& vs,
68*c8dee2aaSAndroid Build Coastguard Worker const SkString& fs) {
69*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kMax = 10;
70*c8dee2aaSAndroid Build Coastguard Worker SkString result;
71*c8dee2aaSAndroid Build Coastguard Worker result.appendf("Attributes (count=%zu, stride=%zu):\n", attributes.size(), stride);
72*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::min(kMax, attributes.size()); ++i) {
73*c8dee2aaSAndroid Build Coastguard Worker const auto& a = attributes[i];
74*c8dee2aaSAndroid Build Coastguard Worker result.appendf(" {%-10s, %3zu, \"%s\"}\n", attr_type_str(a.type), a.offset, a.name.c_str());
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker if (kMax < attributes.size()) {
77*c8dee2aaSAndroid Build Coastguard Worker result.append(" ...\n");
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker result.appendf("Varyings (count=%zu):\n", varyings.size());
81*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::min(kMax, varyings.size()); ++i) {
82*c8dee2aaSAndroid Build Coastguard Worker const auto& v = varyings[i];
83*c8dee2aaSAndroid Build Coastguard Worker result.appendf(" {%5s, \"%s\"}\n", var_type_str(v.type), v.name.c_str());
84*c8dee2aaSAndroid Build Coastguard Worker }
85*c8dee2aaSAndroid Build Coastguard Worker if (kMax < varyings.size()) {
86*c8dee2aaSAndroid Build Coastguard Worker result.append(" ...\n");
87*c8dee2aaSAndroid Build Coastguard Worker }
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker result.appendf("\n--VS--\n%s\n------\n", vs.c_str());
90*c8dee2aaSAndroid Build Coastguard Worker result.appendf("\n--FS--\n%s\n------\n", fs.c_str());
91*c8dee2aaSAndroid Build Coastguard Worker return result;
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker
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)94*c8dee2aaSAndroid Build Coastguard Worker static bool check_for_failure(skiatest::Reporter* reporter,
95*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Attribute> attributes,
96*c8dee2aaSAndroid Build Coastguard Worker size_t stride,
97*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Varying> varyings,
98*c8dee2aaSAndroid Build Coastguard Worker const SkString& vs,
99*c8dee2aaSAndroid Build Coastguard Worker const SkString& fs,
100*c8dee2aaSAndroid Build Coastguard Worker const char* expectedErrorSubstring = nullptr) {
101*c8dee2aaSAndroid Build Coastguard Worker auto [spec, error] = SkMeshSpecification::Make(attributes, stride, varyings, vs, fs);
102*c8dee2aaSAndroid Build Coastguard Worker if (spec) {
103*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
104*c8dee2aaSAndroid Build Coastguard Worker "Expected to fail but succeeded:\n%s",
105*c8dee2aaSAndroid Build Coastguard Worker make_description(attributes, stride, varyings, vs, fs).c_str());
106*c8dee2aaSAndroid Build Coastguard Worker return false;
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker if (expectedErrorSubstring && !error.contains(expectedErrorSubstring)) {
109*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
110*c8dee2aaSAndroid Build Coastguard Worker " Expected: %s\n"
111*c8dee2aaSAndroid Build Coastguard Worker "Actual error: %s\n",
112*c8dee2aaSAndroid Build Coastguard Worker expectedErrorSubstring, error.c_str());
113*c8dee2aaSAndroid Build Coastguard Worker return false;
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker return true;
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker
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)118*c8dee2aaSAndroid Build Coastguard Worker static bool check_for_success(skiatest::Reporter* reporter,
119*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Attribute> attributes,
120*c8dee2aaSAndroid Build Coastguard Worker size_t stride,
121*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Varying> varyings,
122*c8dee2aaSAndroid Build Coastguard Worker const SkString& vs,
123*c8dee2aaSAndroid Build Coastguard Worker const SkString& fs,
124*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMeshSpecification>* spec = nullptr) {
125*c8dee2aaSAndroid Build Coastguard Worker auto [s, error] = SkMeshSpecification::Make(attributes, stride, varyings, vs, fs);
126*c8dee2aaSAndroid Build Coastguard Worker if (s) {
127*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, error.isEmpty());
128*c8dee2aaSAndroid Build Coastguard Worker if (spec) {
129*c8dee2aaSAndroid Build Coastguard Worker *spec = std::move(s);
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker return true;
132*c8dee2aaSAndroid Build Coastguard Worker }
133*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
134*c8dee2aaSAndroid Build Coastguard Worker "Expected to succeed but failed:\n%sError:\n%s",
135*c8dee2aaSAndroid Build Coastguard Worker make_description(attributes, stride, varyings, vs, fs).c_str(),
136*c8dee2aaSAndroid Build Coastguard Worker error.c_str());
137*c8dee2aaSAndroid Build Coastguard Worker return false;
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker // Simple valid strings to make specifications
141*c8dee2aaSAndroid Build Coastguard Worker static const SkString kValidVS {R"(
142*c8dee2aaSAndroid Build Coastguard Worker Varyings main(const Attributes attrs) {
143*c8dee2aaSAndroid Build Coastguard Worker Varyings v;
144*c8dee2aaSAndroid Build Coastguard Worker return v;
145*c8dee2aaSAndroid Build Coastguard Worker })"};
146*c8dee2aaSAndroid Build Coastguard Worker
147*c8dee2aaSAndroid Build Coastguard Worker // There are multiple valid VS signatures.
148*c8dee2aaSAndroid Build Coastguard Worker static const SkString kValidFSes[]{
149*c8dee2aaSAndroid Build Coastguard Worker SkString{"float2 main(const Varyings varyings) { return float2(10); }"},
150*c8dee2aaSAndroid Build Coastguard Worker SkString{R"(
151*c8dee2aaSAndroid Build Coastguard Worker float2 main(const Varyings varyings, out half4 color) {
152*c8dee2aaSAndroid Build Coastguard Worker color = half4(.2);
153*c8dee2aaSAndroid Build Coastguard Worker return float2(10);
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker )"},
156*c8dee2aaSAndroid Build Coastguard Worker };
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker // Simple valid attributes, stride, and varyings to make specifications
159*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kValidAttrs[] = {
160*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat4, 0, SkString{"pos"}},
161*c8dee2aaSAndroid Build Coastguard Worker };
162*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kValidStride = 4*4;
163*c8dee2aaSAndroid Build Coastguard Worker static const Varying kValidVaryings[] = {
164*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat2, SkString{"uv"}},
165*c8dee2aaSAndroid Build Coastguard Worker };
166*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_Valid,reporter)167*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_Valid, reporter) {
168*c8dee2aaSAndroid Build Coastguard Worker for (const auto& validFS : kValidFSes) {
169*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_success(reporter,
170*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
171*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
172*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
173*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
174*c8dee2aaSAndroid Build Coastguard Worker validFS)) {
175*c8dee2aaSAndroid Build Coastguard Worker return;
176*c8dee2aaSAndroid Build Coastguard Worker }
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_InvalidSignature,reporter)180*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_InvalidSignature, reporter) {
181*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kVSBody = "{ return float2(10); }";
182*c8dee2aaSAndroid Build Coastguard Worker
183*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kInvalidVSSigs[] {
184*c8dee2aaSAndroid Build Coastguard Worker "float3 main(const Attributes attrs)", // bad return
185*c8dee2aaSAndroid Build Coastguard Worker "Varyings main(Attributes attrs)", // non-const Attributes
186*c8dee2aaSAndroid Build Coastguard Worker "Varyings main(out Attributes attrs)", // out Varyings
187*c8dee2aaSAndroid Build Coastguard Worker "Varyings main()", // no Attributes
188*c8dee2aaSAndroid Build Coastguard Worker "Varyings main(const Varyings v, float2)" // extra arg
189*c8dee2aaSAndroid Build Coastguard Worker };
190*c8dee2aaSAndroid Build Coastguard Worker
191*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kNoColorFSBody = "{ return float2(10); }";
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kInvalidNoColorFSSigs[] {
194*c8dee2aaSAndroid Build Coastguard Worker "half2 main(const Varyings v)", // bad return
195*c8dee2aaSAndroid Build Coastguard Worker "float2 main(const Attributes v)", // wrong param type
196*c8dee2aaSAndroid Build Coastguard Worker "float2 main(inout Varyings attrs)", // inout Varyings
197*c8dee2aaSAndroid Build Coastguard Worker "float2 main(Varyings v)", // non-const Varyings
198*c8dee2aaSAndroid Build Coastguard Worker "float2 main()", // no args
199*c8dee2aaSAndroid Build Coastguard Worker "float2 main(const Varyings, float)" // extra arg
200*c8dee2aaSAndroid Build Coastguard Worker };
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kColorFSBody = "{ color = half4(.2); return float2(10); }";
203*c8dee2aaSAndroid Build Coastguard Worker
204*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kInvalidColorFSSigs[] {
205*c8dee2aaSAndroid Build Coastguard Worker "half2 main(const Varyings v, out half4 color)", // bad return
206*c8dee2aaSAndroid Build Coastguard Worker "float2 main(const Attributes v, out half4 color)", // wrong first param type
207*c8dee2aaSAndroid Build Coastguard Worker "float2 main(const Varyings v, out half3 color)", // wrong second param type
208*c8dee2aaSAndroid Build Coastguard Worker "float2 main(out Varyings v, out half4 color)", // out Varyings
209*c8dee2aaSAndroid Build Coastguard Worker "float2 main(const Varyings v, half4 color)", // in color
210*c8dee2aaSAndroid Build Coastguard Worker "float2 main(const Varyings v, out half4 color, float)" // extra arg
211*c8dee2aaSAndroid Build Coastguard Worker };
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker for (const char* vsSig : kInvalidVSSigs) {
214*c8dee2aaSAndroid Build Coastguard Worker SkString invalidVS;
215*c8dee2aaSAndroid Build Coastguard Worker invalidVS.appendf("%s %s", vsSig, kVSBody);
216*c8dee2aaSAndroid Build Coastguard Worker for (const auto& validFS : kValidFSes) {
217*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
218*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
219*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
220*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
221*c8dee2aaSAndroid Build Coastguard Worker invalidVS,
222*c8dee2aaSAndroid Build Coastguard Worker validFS)) {
223*c8dee2aaSAndroid Build Coastguard Worker return;
224*c8dee2aaSAndroid Build Coastguard Worker }
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker
228*c8dee2aaSAndroid Build Coastguard Worker for (const char* noColorFSSig : kInvalidNoColorFSSigs) {
229*c8dee2aaSAndroid Build Coastguard Worker SkString invalidFS;
230*c8dee2aaSAndroid Build Coastguard Worker invalidFS.appendf("%s %s", noColorFSSig, kNoColorFSBody);
231*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
232*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
233*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
234*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
235*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
236*c8dee2aaSAndroid Build Coastguard Worker invalidFS)) {
237*c8dee2aaSAndroid Build Coastguard Worker return;
238*c8dee2aaSAndroid Build Coastguard Worker }
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker for (const char* colorFSSig : kInvalidColorFSSigs) {
242*c8dee2aaSAndroid Build Coastguard Worker SkString invalidFS;
243*c8dee2aaSAndroid Build Coastguard Worker invalidFS.appendf("%s %s", colorFSSig, kColorFSBody);
244*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
245*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
246*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
247*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
248*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
249*c8dee2aaSAndroid Build Coastguard Worker invalidFS)) {
250*c8dee2aaSAndroid Build Coastguard Worker return;
251*c8dee2aaSAndroid Build Coastguard Worker }
252*c8dee2aaSAndroid Build Coastguard Worker }
253*c8dee2aaSAndroid Build Coastguard Worker }
254*c8dee2aaSAndroid Build Coastguard Worker
255*c8dee2aaSAndroid Build Coastguard Worker // We allow the optional out color from the FS to either be float4 or half4
DEF_TEST(MeshSpec_Float4Color,reporter)256*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_Float4Color, reporter) {
257*c8dee2aaSAndroid Build Coastguard Worker static const SkString kFloat4FS {
258*c8dee2aaSAndroid Build Coastguard Worker R"(
259*c8dee2aaSAndroid Build Coastguard Worker float2 main(const Varyings varyings, out float4 color) {
260*c8dee2aaSAndroid Build Coastguard Worker color = float4(.2); return float2(10);
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker )"
263*c8dee2aaSAndroid Build Coastguard Worker };
264*c8dee2aaSAndroid Build Coastguard Worker check_for_success(reporter,
265*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
266*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
267*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
268*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
269*c8dee2aaSAndroid Build Coastguard Worker kFloat4FS);
270*c8dee2aaSAndroid Build Coastguard Worker }
271*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_DisallowsChildEffectInVertex,reporter)272*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_DisallowsChildEffectInVertex, reporter) {
273*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kChildEffects[] {
274*c8dee2aaSAndroid Build Coastguard Worker "uniform shader myshader;",
275*c8dee2aaSAndroid Build Coastguard Worker "uniform colorFilter mycolorfilter;",
276*c8dee2aaSAndroid Build Coastguard Worker "uniform blender myblender;"
277*c8dee2aaSAndroid Build Coastguard Worker };
278*c8dee2aaSAndroid Build Coastguard Worker
279*c8dee2aaSAndroid Build Coastguard Worker for (const auto& global : kChildEffects) {
280*c8dee2aaSAndroid Build Coastguard Worker SkString vsWithChild{global};
281*c8dee2aaSAndroid Build Coastguard Worker vsWithChild.append(kValidVS);
282*c8dee2aaSAndroid Build Coastguard Worker
283*c8dee2aaSAndroid Build Coastguard Worker SkString fsWithChild{global};
284*c8dee2aaSAndroid Build Coastguard Worker fsWithChild.append(kValidFSes[0]);
285*c8dee2aaSAndroid Build Coastguard Worker
286*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
287*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
288*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
289*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
290*c8dee2aaSAndroid Build Coastguard Worker vsWithChild,
291*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0],
292*c8dee2aaSAndroid Build Coastguard Worker "effects are not permitted in mesh vertex shaders")) {
293*c8dee2aaSAndroid Build Coastguard Worker return;
294*c8dee2aaSAndroid Build Coastguard Worker }
295*c8dee2aaSAndroid Build Coastguard Worker
296*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
297*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
298*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
299*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
300*c8dee2aaSAndroid Build Coastguard Worker vsWithChild,
301*c8dee2aaSAndroid Build Coastguard Worker fsWithChild,
302*c8dee2aaSAndroid Build Coastguard Worker "effects are not permitted in mesh vertex shaders")) {
303*c8dee2aaSAndroid Build Coastguard Worker return;
304*c8dee2aaSAndroid Build Coastguard Worker }
305*c8dee2aaSAndroid Build Coastguard Worker }
306*c8dee2aaSAndroid Build Coastguard Worker }
307*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_AllowsChildEffectInFragment,reporter)308*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_AllowsChildEffectInFragment, reporter) {
309*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kChildEffects[] {
310*c8dee2aaSAndroid Build Coastguard Worker "uniform shader myshader;",
311*c8dee2aaSAndroid Build Coastguard Worker "uniform colorFilter mycolorfilter; uniform shader myshader;",
312*c8dee2aaSAndroid Build Coastguard Worker "uniform shader myshader; uniform blender myblender; uniform colorFilter mycolorfilter;"
313*c8dee2aaSAndroid Build Coastguard Worker };
314*c8dee2aaSAndroid Build Coastguard Worker
315*c8dee2aaSAndroid Build Coastguard Worker for (const auto& global : kChildEffects) {
316*c8dee2aaSAndroid Build Coastguard Worker SkString fsWithChild{global};
317*c8dee2aaSAndroid Build Coastguard Worker fsWithChild.append(kValidFSes[0]);
318*c8dee2aaSAndroid Build Coastguard Worker
319*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_success(reporter,
320*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
321*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
322*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
323*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
324*c8dee2aaSAndroid Build Coastguard Worker fsWithChild)) {
325*c8dee2aaSAndroid Build Coastguard Worker return;
326*c8dee2aaSAndroid Build Coastguard Worker }
327*c8dee2aaSAndroid Build Coastguard Worker }
328*c8dee2aaSAndroid Build Coastguard Worker }
329*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_FindChild,reporter)330*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_FindChild, reporter) {
331*c8dee2aaSAndroid Build Coastguard Worker SkString fsWithChild{"uniform shader myshader;"
332*c8dee2aaSAndroid Build Coastguard Worker "uniform blender myblender;"
333*c8dee2aaSAndroid Build Coastguard Worker "uniform colorFilter mycolorfilter;"};
334*c8dee2aaSAndroid Build Coastguard Worker fsWithChild.append(kValidFSes[0]);
335*c8dee2aaSAndroid Build Coastguard Worker
336*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMeshSpecification> meshSpec;
337*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_success(reporter,
338*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
339*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
340*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
341*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
342*c8dee2aaSAndroid Build Coastguard Worker fsWithChild,
343*c8dee2aaSAndroid Build Coastguard Worker &meshSpec)) {
344*c8dee2aaSAndroid Build Coastguard Worker return;
345*c8dee2aaSAndroid Build Coastguard Worker }
346*c8dee2aaSAndroid Build Coastguard Worker
347*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, meshSpec->findChild("myshader")->index == 0);
348*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, meshSpec->findChild("myblender")->index == 1);
349*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, meshSpec->findChild("mycolorfilter")->index == 2);
350*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !meshSpec->findChild("missing"));
351*c8dee2aaSAndroid Build Coastguard Worker }
352*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Mesh_ChildEffectsMatchSpec,reporter)353*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Mesh_ChildEffectsMatchSpec, reporter) {
354*c8dee2aaSAndroid Build Coastguard Worker auto test = [&](const char* prefix,
355*c8dee2aaSAndroid Build Coastguard Worker SkSpan<SkRuntimeEffect::ChildPtr> children,
356*c8dee2aaSAndroid Build Coastguard Worker const char* expectedError = nullptr) {
357*c8dee2aaSAndroid Build Coastguard Worker SkString fsWithChild{prefix};
358*c8dee2aaSAndroid Build Coastguard Worker fsWithChild.append(kValidFSes[0]);
359*c8dee2aaSAndroid Build Coastguard Worker
360*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMeshSpecification> meshSpec;
361*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_success(reporter,
362*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
363*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
364*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
365*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
366*c8dee2aaSAndroid Build Coastguard Worker fsWithChild,
367*c8dee2aaSAndroid Build Coastguard Worker &meshSpec)) {
368*c8dee2aaSAndroid Build Coastguard Worker return;
369*c8dee2aaSAndroid Build Coastguard Worker }
370*c8dee2aaSAndroid Build Coastguard Worker
371*c8dee2aaSAndroid Build Coastguard Worker constexpr float kVertexCount = 4;
372*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMesh::VertexBuffer> vertexBuffer =
373*c8dee2aaSAndroid Build Coastguard Worker SkMeshes::MakeVertexBuffer(nullptr, kValidStride * kVertexCount);
374*c8dee2aaSAndroid Build Coastguard Worker SkMesh::Result result = SkMesh::Make(meshSpec,
375*c8dee2aaSAndroid Build Coastguard Worker SkMesh::Mode::kTriangleStrip,
376*c8dee2aaSAndroid Build Coastguard Worker vertexBuffer,
377*c8dee2aaSAndroid Build Coastguard Worker kVertexCount,
378*c8dee2aaSAndroid Build Coastguard Worker /*vertexOffset=*/0,
379*c8dee2aaSAndroid Build Coastguard Worker /*uniforms=*/nullptr,
380*c8dee2aaSAndroid Build Coastguard Worker children,
381*c8dee2aaSAndroid Build Coastguard Worker SkRect::MakeEmpty());
382*c8dee2aaSAndroid Build Coastguard Worker
383*c8dee2aaSAndroid Build Coastguard Worker if (expectedError) {
384*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !result.mesh.isValid());
385*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
386*c8dee2aaSAndroid Build Coastguard Worker result.error.contains(expectedError),
387*c8dee2aaSAndroid Build Coastguard Worker "Expected: '%s'\n"
388*c8dee2aaSAndroid Build Coastguard Worker " Actual: '%s'\n", expectedError, result.error.c_str());
389*c8dee2aaSAndroid Build Coastguard Worker } else {
390*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, result.mesh.isValid());
391*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
392*c8dee2aaSAndroid Build Coastguard Worker result.error.isEmpty(),
393*c8dee2aaSAndroid Build Coastguard Worker "Expected: no errors\n"
394*c8dee2aaSAndroid Build Coastguard Worker " Actual: '%s'\n", result.error.c_str());
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker };
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker SkRuntimeEffect::ChildPtr childShader[] = {SkShaders::Color(SK_ColorBLACK)};
399*c8dee2aaSAndroid Build Coastguard Worker SkRuntimeEffect::ChildPtr childFilter[] = {SkColorFilters::LinearToSRGBGamma()};
400*c8dee2aaSAndroid Build Coastguard Worker SkRuntimeEffect::ChildPtr childBlender[] = {SkBlender::Mode(SkBlendMode::kSrcOver)};
401*c8dee2aaSAndroid Build Coastguard Worker SkRuntimeEffect::ChildPtr childNull[1] = {};
402*c8dee2aaSAndroid Build Coastguard Worker
403*c8dee2aaSAndroid Build Coastguard Worker // These are expected to report a count mismatch.
404*c8dee2aaSAndroid Build Coastguard Worker test("uniform shader myshader;", {},
405*c8dee2aaSAndroid Build Coastguard Worker "The mesh specification declares 1 child effects, but the mesh supplies 0.");
406*c8dee2aaSAndroid Build Coastguard Worker test("", childShader,
407*c8dee2aaSAndroid Build Coastguard Worker "The mesh specification declares 0 child effects, but the mesh supplies 1.");
408*c8dee2aaSAndroid Build Coastguard Worker
409*c8dee2aaSAndroid Build Coastguard Worker // These are expected to report a type mismatch.
410*c8dee2aaSAndroid Build Coastguard Worker test("uniform shader myshader;", childFilter,
411*c8dee2aaSAndroid Build Coastguard Worker "Child effect 'myshader' was specified as a shader, but passed as a color filter.");
412*c8dee2aaSAndroid Build Coastguard Worker test("uniform shader myshader;", childBlender,
413*c8dee2aaSAndroid Build Coastguard Worker "Child effect 'myshader' was specified as a shader, but passed as a blender.");
414*c8dee2aaSAndroid Build Coastguard Worker test("uniform colorFilter myfilter;", childShader,
415*c8dee2aaSAndroid Build Coastguard Worker "Child effect 'myfilter' was specified as a color filter, but passed as a shader.");
416*c8dee2aaSAndroid Build Coastguard Worker test("uniform colorFilter myfilter;", childBlender,
417*c8dee2aaSAndroid Build Coastguard Worker "Child effect 'myfilter' was specified as a color filter, but passed as a blender.");
418*c8dee2aaSAndroid Build Coastguard Worker test("uniform blender myblender;", childShader,
419*c8dee2aaSAndroid Build Coastguard Worker "Child effect 'myblender' was specified as a blender, but passed as a shader.");
420*c8dee2aaSAndroid Build Coastguard Worker test("uniform blender myblender;", childFilter,
421*c8dee2aaSAndroid Build Coastguard Worker "Child effect 'myblender' was specified as a blender, but passed as a color filter.");
422*c8dee2aaSAndroid Build Coastguard Worker
423*c8dee2aaSAndroid Build Coastguard Worker // Null children are supported.
424*c8dee2aaSAndroid Build Coastguard Worker test("uniform shader myshader;", childNull);
425*c8dee2aaSAndroid Build Coastguard Worker test("uniform shader myfilter;", childNull);
426*c8dee2aaSAndroid Build Coastguard Worker test("uniform shader myblender;", childNull);
427*c8dee2aaSAndroid Build Coastguard Worker
428*c8dee2aaSAndroid Build Coastguard Worker // Properly-typed child effects are supported.
429*c8dee2aaSAndroid Build Coastguard Worker test("uniform shader myshader;", childShader);
430*c8dee2aaSAndroid Build Coastguard Worker test("uniform colorFilter myfilter;", childFilter);
431*c8dee2aaSAndroid Build Coastguard Worker test("uniform blender myblender;", childBlender);
432*c8dee2aaSAndroid Build Coastguard Worker
433*c8dee2aaSAndroid Build Coastguard Worker }
434*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_ValidUniforms,reporter)435*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_ValidUniforms, reporter) {
436*c8dee2aaSAndroid Build Coastguard Worker using Uniform = SkMeshSpecification::Uniform;
437*c8dee2aaSAndroid Build Coastguard Worker using Type = Uniform::Type;
438*c8dee2aaSAndroid Build Coastguard Worker using Flags = Uniform::Flags;
439*c8dee2aaSAndroid Build Coastguard Worker
440*c8dee2aaSAndroid Build Coastguard Worker constexpr Flags kVS = Uniform::kVertex_Flag;
441*c8dee2aaSAndroid Build Coastguard Worker constexpr Flags kFS = Uniform::kFragment_Flag;
442*c8dee2aaSAndroid Build Coastguard Worker constexpr Flags kColor = Uniform::kColor_Flag;
443*c8dee2aaSAndroid Build Coastguard Worker constexpr Flags kHalfP = Uniform::kHalfPrecision_Flag;
444*c8dee2aaSAndroid Build Coastguard Worker
445*c8dee2aaSAndroid Build Coastguard Worker auto make_uni = [](Type type,
446*c8dee2aaSAndroid Build Coastguard Worker std::string_view name,
447*c8dee2aaSAndroid Build Coastguard Worker size_t offset,
448*c8dee2aaSAndroid Build Coastguard Worker uint32_t flags,
449*c8dee2aaSAndroid Build Coastguard Worker int count = 0) {
450*c8dee2aaSAndroid Build Coastguard Worker if (count) {
451*c8dee2aaSAndroid Build Coastguard Worker return Uniform{name, offset, type, count, flags | Uniform::kArray_Flag};
452*c8dee2aaSAndroid Build Coastguard Worker } else {
453*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!(flags & Uniform::kArray_Flag));
454*c8dee2aaSAndroid Build Coastguard Worker return Uniform{name, offset, type, 1, flags};
455*c8dee2aaSAndroid Build Coastguard Worker }
456*c8dee2aaSAndroid Build Coastguard Worker };
457*c8dee2aaSAndroid Build Coastguard Worker
458*c8dee2aaSAndroid Build Coastguard Worker // Each test case is a set of VS and FS uniform declarations followed and the expected output
459*c8dee2aaSAndroid Build Coastguard Worker // of SkMeshSpecification::uniforms().
460*c8dee2aaSAndroid Build Coastguard Worker struct {
461*c8dee2aaSAndroid Build Coastguard Worker const std::vector<const char*> vsUniformDecls;
462*c8dee2aaSAndroid Build Coastguard Worker const std::vector<const char*> fsUniformDecls;
463*c8dee2aaSAndroid Build Coastguard Worker const std::vector<SkMeshSpecification::Uniform> expectations;
464*c8dee2aaSAndroid Build Coastguard Worker } static kTestCases[] {
465*c8dee2aaSAndroid Build Coastguard Worker // A single VS uniform.
466*c8dee2aaSAndroid Build Coastguard Worker {
467*c8dee2aaSAndroid Build Coastguard Worker {
468*c8dee2aaSAndroid Build Coastguard Worker "uniform float x;"
469*c8dee2aaSAndroid Build Coastguard Worker },
470*c8dee2aaSAndroid Build Coastguard Worker {},
471*c8dee2aaSAndroid Build Coastguard Worker {
472*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat, "x", 0, kVS)
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker },
475*c8dee2aaSAndroid Build Coastguard Worker
476*c8dee2aaSAndroid Build Coastguard Worker // A single FS uniform.
477*c8dee2aaSAndroid Build Coastguard Worker {
478*c8dee2aaSAndroid Build Coastguard Worker {},
479*c8dee2aaSAndroid Build Coastguard Worker {
480*c8dee2aaSAndroid Build Coastguard Worker "uniform float2 v;"
481*c8dee2aaSAndroid Build Coastguard Worker },
482*c8dee2aaSAndroid Build Coastguard Worker {
483*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat2, "v", 0, kFS)
484*c8dee2aaSAndroid Build Coastguard Worker }
485*c8dee2aaSAndroid Build Coastguard Worker },
486*c8dee2aaSAndroid Build Coastguard Worker
487*c8dee2aaSAndroid Build Coastguard Worker // A single uniform in both that uses color layout.
488*c8dee2aaSAndroid Build Coastguard Worker {
489*c8dee2aaSAndroid Build Coastguard Worker {
490*c8dee2aaSAndroid Build Coastguard Worker "layout(color) uniform float4 color;",
491*c8dee2aaSAndroid Build Coastguard Worker },
492*c8dee2aaSAndroid Build Coastguard Worker {
493*c8dee2aaSAndroid Build Coastguard Worker "layout(color) uniform float4 color;",
494*c8dee2aaSAndroid Build Coastguard Worker },
495*c8dee2aaSAndroid Build Coastguard Worker {
496*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat4, "color", 0, kVS|kFS|kColor)
497*c8dee2aaSAndroid Build Coastguard Worker }
498*c8dee2aaSAndroid Build Coastguard Worker },
499*c8dee2aaSAndroid Build Coastguard Worker
500*c8dee2aaSAndroid Build Coastguard Worker // A shared uniform after an unshared vertex uniform
501*c8dee2aaSAndroid Build Coastguard Worker {
502*c8dee2aaSAndroid Build Coastguard Worker {
503*c8dee2aaSAndroid Build Coastguard Worker "layout(color) uniform float4 color;",
504*c8dee2aaSAndroid Build Coastguard Worker " uniform float x[5];",
505*c8dee2aaSAndroid Build Coastguard Worker },
506*c8dee2aaSAndroid Build Coastguard Worker {
507*c8dee2aaSAndroid Build Coastguard Worker "uniform float x[5];",
508*c8dee2aaSAndroid Build Coastguard Worker },
509*c8dee2aaSAndroid Build Coastguard Worker {
510*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat4, "color", 0, kVS|kColor, 0),
511*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat , "x" , 16, kVS|kFS , 5)
512*c8dee2aaSAndroid Build Coastguard Worker }
513*c8dee2aaSAndroid Build Coastguard Worker },
514*c8dee2aaSAndroid Build Coastguard Worker
515*c8dee2aaSAndroid Build Coastguard Worker // A shared uniform before an unshared vertex uniform
516*c8dee2aaSAndroid Build Coastguard Worker {
517*c8dee2aaSAndroid Build Coastguard Worker {
518*c8dee2aaSAndroid Build Coastguard Worker "uniform half x[2];",
519*c8dee2aaSAndroid Build Coastguard Worker "uniform int y;",
520*c8dee2aaSAndroid Build Coastguard Worker },
521*c8dee2aaSAndroid Build Coastguard Worker {
522*c8dee2aaSAndroid Build Coastguard Worker "uniform half x[2];",
523*c8dee2aaSAndroid Build Coastguard Worker },
524*c8dee2aaSAndroid Build Coastguard Worker {
525*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat, "x", 0, kVS|kFS|kHalfP, 2),
526*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kInt, "y", 8, kVS , 0)
527*c8dee2aaSAndroid Build Coastguard Worker }
528*c8dee2aaSAndroid Build Coastguard Worker },
529*c8dee2aaSAndroid Build Coastguard Worker
530*c8dee2aaSAndroid Build Coastguard Worker // A shared uniform after an unshared fragment uniform
531*c8dee2aaSAndroid Build Coastguard Worker {
532*c8dee2aaSAndroid Build Coastguard Worker {
533*c8dee2aaSAndroid Build Coastguard Worker "uniform float3x3 m;",
534*c8dee2aaSAndroid Build Coastguard Worker },
535*c8dee2aaSAndroid Build Coastguard Worker {
536*c8dee2aaSAndroid Build Coastguard Worker "uniform int2 i2;",
537*c8dee2aaSAndroid Build Coastguard Worker "uniform float3x3 m;",
538*c8dee2aaSAndroid Build Coastguard Worker },
539*c8dee2aaSAndroid Build Coastguard Worker {
540*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat3x3, "m" , 0, kVS|kFS),
541*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kInt2 , "i2", 36, kFS )
542*c8dee2aaSAndroid Build Coastguard Worker }
543*c8dee2aaSAndroid Build Coastguard Worker },
544*c8dee2aaSAndroid Build Coastguard Worker
545*c8dee2aaSAndroid Build Coastguard Worker // A shared uniform before an unshared fragment uniform
546*c8dee2aaSAndroid Build Coastguard Worker {
547*c8dee2aaSAndroid Build Coastguard Worker {
548*c8dee2aaSAndroid Build Coastguard Worker "uniform half4x4 m[4];",
549*c8dee2aaSAndroid Build Coastguard Worker },
550*c8dee2aaSAndroid Build Coastguard Worker {
551*c8dee2aaSAndroid Build Coastguard Worker "uniform half4x4 m[4];",
552*c8dee2aaSAndroid Build Coastguard Worker "uniform int3 i3[1];",
553*c8dee2aaSAndroid Build Coastguard Worker },
554*c8dee2aaSAndroid Build Coastguard Worker {
555*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat4x4, "m", 0, kVS|kFS|kHalfP, 4),
556*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kInt3, "i3", 256, kFS , 1)
557*c8dee2aaSAndroid Build Coastguard Worker }
558*c8dee2aaSAndroid Build Coastguard Worker },
559*c8dee2aaSAndroid Build Coastguard Worker
560*c8dee2aaSAndroid Build Coastguard Worker // Complex case with 2 shared uniforms that are declared in the opposite order.
561*c8dee2aaSAndroid Build Coastguard Worker {
562*c8dee2aaSAndroid Build Coastguard Worker {
563*c8dee2aaSAndroid Build Coastguard Worker "uniform float x;"
564*c8dee2aaSAndroid Build Coastguard Worker "uniform half4x4 m[4];", // shared
565*c8dee2aaSAndroid Build Coastguard Worker "uniform int2 i2[2];"
566*c8dee2aaSAndroid Build Coastguard Worker "uniform float3 v[8];" // shared
567*c8dee2aaSAndroid Build Coastguard Worker "uniform int3 i3;"
568*c8dee2aaSAndroid Build Coastguard Worker },
569*c8dee2aaSAndroid Build Coastguard Worker {
570*c8dee2aaSAndroid Build Coastguard Worker "uniform float y;"
571*c8dee2aaSAndroid Build Coastguard Worker "uniform float3 v[8];" // shared
572*c8dee2aaSAndroid Build Coastguard Worker "uniform int4 i4[2];"
573*c8dee2aaSAndroid Build Coastguard Worker "uniform half4x4 m[4];", // shared
574*c8dee2aaSAndroid Build Coastguard Worker "uniform int i;"
575*c8dee2aaSAndroid Build Coastguard Worker },
576*c8dee2aaSAndroid Build Coastguard Worker {
577*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat, "x" , 0, kVS , 0),
578*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat4x4, "m" , 4, kVS|kFS|kHalfP, 4),
579*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kInt2, "i2", 260, kVS , 2),
580*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat3, "v" , 276, kVS|kFS , 8),
581*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kInt3, "i3", 372, kVS , 0),
582*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kFloat, "y" , 384, kFS , 0),
583*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kInt4, "i4", 388, kFS , 2),
584*c8dee2aaSAndroid Build Coastguard Worker make_uni(Type::kInt, "i" , 420, kFS , 0),
585*c8dee2aaSAndroid Build Coastguard Worker }
586*c8dee2aaSAndroid Build Coastguard Worker },
587*c8dee2aaSAndroid Build Coastguard Worker };
588*c8dee2aaSAndroid Build Coastguard Worker
589*c8dee2aaSAndroid Build Coastguard Worker for (const auto& c : kTestCases) {
590*c8dee2aaSAndroid Build Coastguard Worker SkString vs = kValidVS;
591*c8dee2aaSAndroid Build Coastguard Worker SkString unis;
592*c8dee2aaSAndroid Build Coastguard Worker for (const auto u : c.vsUniformDecls) {
593*c8dee2aaSAndroid Build Coastguard Worker unis.append(u);
594*c8dee2aaSAndroid Build Coastguard Worker }
595*c8dee2aaSAndroid Build Coastguard Worker vs.prepend(unis);
596*c8dee2aaSAndroid Build Coastguard Worker
597*c8dee2aaSAndroid Build Coastguard Worker SkString fs = kValidFSes[0];
598*c8dee2aaSAndroid Build Coastguard Worker unis = {};
599*c8dee2aaSAndroid Build Coastguard Worker for (const auto u : c.fsUniformDecls) {
600*c8dee2aaSAndroid Build Coastguard Worker unis.append(u);
601*c8dee2aaSAndroid Build Coastguard Worker }
602*c8dee2aaSAndroid Build Coastguard Worker fs.prepend(unis);
603*c8dee2aaSAndroid Build Coastguard Worker
604*c8dee2aaSAndroid Build Coastguard Worker auto attrs = SkSpan(kValidAttrs);
605*c8dee2aaSAndroid Build Coastguard Worker auto varys = SkSpan(kValidVaryings);
606*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkMeshSpecification> spec;
607*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_success(reporter, attrs, kValidStride, varys, vs, fs, &spec)) {
608*c8dee2aaSAndroid Build Coastguard Worker return;
609*c8dee2aaSAndroid Build Coastguard Worker }
610*c8dee2aaSAndroid Build Coastguard Worker SkString desc = make_description(attrs, kValidStride, varys, vs, fs);
611*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Uniform> uniforms = spec->uniforms();
612*c8dee2aaSAndroid Build Coastguard Worker if (uniforms.size() != c.expectations.size()) {
613*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
614*c8dee2aaSAndroid Build Coastguard Worker "Expected %zu uniforms but actually %zu:\n%s",
615*c8dee2aaSAndroid Build Coastguard Worker c.expectations.size(),
616*c8dee2aaSAndroid Build Coastguard Worker uniforms.size(),
617*c8dee2aaSAndroid Build Coastguard Worker desc.c_str());
618*c8dee2aaSAndroid Build Coastguard Worker return;
619*c8dee2aaSAndroid Build Coastguard Worker }
620*c8dee2aaSAndroid Build Coastguard Worker for (const auto& [actual, expected] : SkMakeZip(uniforms, c.expectations)) {
621*c8dee2aaSAndroid Build Coastguard Worker std::string name = std::string(actual.name);
622*c8dee2aaSAndroid Build Coastguard Worker if (name != expected.name) {
623*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
624*c8dee2aaSAndroid Build Coastguard Worker "Actual uniform name (%s) does not match expected name (%.*s)",
625*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
626*c8dee2aaSAndroid Build Coastguard Worker (int)expected.name.size(), expected.name.data());
627*c8dee2aaSAndroid Build Coastguard Worker return;
628*c8dee2aaSAndroid Build Coastguard Worker }
629*c8dee2aaSAndroid Build Coastguard Worker if (actual.type != expected.type) {
630*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
631*c8dee2aaSAndroid Build Coastguard Worker "Uniform %s: Actual type (%d) does not match expected type (%d)",
632*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
633*c8dee2aaSAndroid Build Coastguard Worker static_cast<int>(actual.type),
634*c8dee2aaSAndroid Build Coastguard Worker static_cast<int>(expected.type));
635*c8dee2aaSAndroid Build Coastguard Worker return;
636*c8dee2aaSAndroid Build Coastguard Worker }
637*c8dee2aaSAndroid Build Coastguard Worker if (actual.count != expected.count) {
638*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
639*c8dee2aaSAndroid Build Coastguard Worker "Uniform %s: Actual count (%d) does not match expected count (%d)",
640*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
641*c8dee2aaSAndroid Build Coastguard Worker actual.count,
642*c8dee2aaSAndroid Build Coastguard Worker expected.count);
643*c8dee2aaSAndroid Build Coastguard Worker return;
644*c8dee2aaSAndroid Build Coastguard Worker }
645*c8dee2aaSAndroid Build Coastguard Worker if (actual.flags != expected.flags) {
646*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
647*c8dee2aaSAndroid Build Coastguard Worker "Uniform %s: Actual flags (0x%04x) do not match expected flags (0x%04x)",
648*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
649*c8dee2aaSAndroid Build Coastguard Worker actual.flags,
650*c8dee2aaSAndroid Build Coastguard Worker expected.flags);
651*c8dee2aaSAndroid Build Coastguard Worker return;
652*c8dee2aaSAndroid Build Coastguard Worker }
653*c8dee2aaSAndroid Build Coastguard Worker if (actual.offset != expected.offset) {
654*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
655*c8dee2aaSAndroid Build Coastguard Worker "Uniform %s: Actual offset (%zu) does not match expected offset (%zu)",
656*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
657*c8dee2aaSAndroid Build Coastguard Worker actual.offset,
658*c8dee2aaSAndroid Build Coastguard Worker expected.offset);
659*c8dee2aaSAndroid Build Coastguard Worker return;
660*c8dee2aaSAndroid Build Coastguard Worker }
661*c8dee2aaSAndroid Build Coastguard Worker }
662*c8dee2aaSAndroid Build Coastguard Worker }
663*c8dee2aaSAndroid Build Coastguard Worker }
664*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_InvalidUniforms,reporter)665*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_InvalidUniforms, reporter) {
666*c8dee2aaSAndroid Build Coastguard Worker // We assume general uniform declarations are broadly tested generically in SkSL. Here we are
667*c8dee2aaSAndroid Build Coastguard Worker // concerned with agreement between VS and FS declarations, which is a unique aspect of
668*c8dee2aaSAndroid Build Coastguard Worker // SkMeshSpecification.
669*c8dee2aaSAndroid Build Coastguard Worker
670*c8dee2aaSAndroid Build Coastguard Worker // Each test case is a fs and vs uniform declaration with the same name but some other
671*c8dee2aaSAndroid Build Coastguard Worker // difference that should make them incompatible.
672*c8dee2aaSAndroid Build Coastguard Worker static std::tuple<const char*, const char*> kTestCases[]{
673*c8dee2aaSAndroid Build Coastguard Worker // different types
674*c8dee2aaSAndroid Build Coastguard Worker {"uniform float x;", "uniform int x;"},
675*c8dee2aaSAndroid Build Coastguard Worker // array vs non-array
676*c8dee2aaSAndroid Build Coastguard Worker {"uniform float2x2 m[1];", "uniform float2x2 m;"},
677*c8dee2aaSAndroid Build Coastguard Worker // array count mismatch
678*c8dee2aaSAndroid Build Coastguard Worker {"uniform int3 i[1];", "uniform int3 i[2];"},
679*c8dee2aaSAndroid Build Coastguard Worker // layout difference
680*c8dee2aaSAndroid Build Coastguard Worker {"layout(color) uniform float4 color;", "uniform float4 color;"},
681*c8dee2aaSAndroid Build Coastguard Worker };
682*c8dee2aaSAndroid Build Coastguard Worker
683*c8dee2aaSAndroid Build Coastguard Worker for (bool reverse : {false, true}) {
684*c8dee2aaSAndroid Build Coastguard Worker for (auto [u1, u2] : kTestCases) {
685*c8dee2aaSAndroid Build Coastguard Worker if (reverse) {
686*c8dee2aaSAndroid Build Coastguard Worker using std::swap;
687*c8dee2aaSAndroid Build Coastguard Worker swap(u1, u2);
688*c8dee2aaSAndroid Build Coastguard Worker }
689*c8dee2aaSAndroid Build Coastguard Worker SkString vs = kValidVS;
690*c8dee2aaSAndroid Build Coastguard Worker vs.prepend(u1);
691*c8dee2aaSAndroid Build Coastguard Worker
692*c8dee2aaSAndroid Build Coastguard Worker SkString fs = kValidFSes[0];
693*c8dee2aaSAndroid Build Coastguard Worker fs.prepend(u2);
694*c8dee2aaSAndroid Build Coastguard Worker
695*c8dee2aaSAndroid Build Coastguard Worker auto attrs = SkSpan(kValidAttrs);
696*c8dee2aaSAndroid Build Coastguard Worker auto varys = SkSpan(kValidVaryings);
697*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter, attrs, kValidStride, varys, vs, fs)) {
698*c8dee2aaSAndroid Build Coastguard Worker return;
699*c8dee2aaSAndroid Build Coastguard Worker }
700*c8dee2aaSAndroid Build Coastguard Worker }
701*c8dee2aaSAndroid Build Coastguard Worker }
702*c8dee2aaSAndroid Build Coastguard Worker }
703*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_MissingMain,reporter)704*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_MissingMain, reporter) {
705*c8dee2aaSAndroid Build Coastguard Worker static const SkString kHelper{"float2 swiz(float2 x) { return z.yx; }"};
706*c8dee2aaSAndroid Build Coastguard Worker
707*c8dee2aaSAndroid Build Coastguard Worker // Empty VS
708*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
709*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
710*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
711*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
712*c8dee2aaSAndroid Build Coastguard Worker SkString{},
713*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
714*c8dee2aaSAndroid Build Coastguard Worker return;
715*c8dee2aaSAndroid Build Coastguard Worker }
716*c8dee2aaSAndroid Build Coastguard Worker
717*c8dee2aaSAndroid Build Coastguard Worker // VS with helper function but no main
718*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
719*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
720*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
721*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
722*c8dee2aaSAndroid Build Coastguard Worker kHelper,
723*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
724*c8dee2aaSAndroid Build Coastguard Worker return;
725*c8dee2aaSAndroid Build Coastguard Worker }
726*c8dee2aaSAndroid Build Coastguard Worker
727*c8dee2aaSAndroid Build Coastguard Worker // Empty FS
728*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
729*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
730*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
731*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
732*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
733*c8dee2aaSAndroid Build Coastguard Worker SkString{})) {
734*c8dee2aaSAndroid Build Coastguard Worker return;
735*c8dee2aaSAndroid Build Coastguard Worker }
736*c8dee2aaSAndroid Build Coastguard Worker
737*c8dee2aaSAndroid Build Coastguard Worker // VS with helper function but no main
738*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
739*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
740*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
741*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
742*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
743*c8dee2aaSAndroid Build Coastguard Worker kHelper)) {
744*c8dee2aaSAndroid Build Coastguard Worker return;
745*c8dee2aaSAndroid Build Coastguard Worker }
746*c8dee2aaSAndroid Build Coastguard Worker }
747*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_ZeroAttributes,reporter)748*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_ZeroAttributes, reporter) {
749*c8dee2aaSAndroid Build Coastguard Worker // We require at least one attribute
750*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
751*c8dee2aaSAndroid Build Coastguard Worker SkSpan<Attribute>(),
752*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
753*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
754*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
755*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
756*c8dee2aaSAndroid Build Coastguard Worker }
757*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_ZeroVaryings,reporter)758*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_ZeroVaryings, reporter) {
759*c8dee2aaSAndroid Build Coastguard Worker // Varyings are not required.
760*c8dee2aaSAndroid Build Coastguard Worker check_for_success(reporter,
761*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
762*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
763*c8dee2aaSAndroid Build Coastguard Worker SkSpan<Varying>(),
764*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
765*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
766*c8dee2aaSAndroid Build Coastguard Worker }
767*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_InvalidStride,reporter)768*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_InvalidStride, reporter) {
769*c8dee2aaSAndroid Build Coastguard Worker // Zero stride
770*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
771*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
772*c8dee2aaSAndroid Build Coastguard Worker 0,
773*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
774*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
775*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
776*c8dee2aaSAndroid Build Coastguard Worker return;
777*c8dee2aaSAndroid Build Coastguard Worker }
778*c8dee2aaSAndroid Build Coastguard Worker
779*c8dee2aaSAndroid Build Coastguard Worker // Unaligned
780*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
781*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
782*c8dee2aaSAndroid Build Coastguard Worker kValidStride + 1,
783*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
784*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
785*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
786*c8dee2aaSAndroid Build Coastguard Worker return;
787*c8dee2aaSAndroid Build Coastguard Worker }
788*c8dee2aaSAndroid Build Coastguard Worker
789*c8dee2aaSAndroid Build Coastguard Worker // Too large
790*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
791*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
792*c8dee2aaSAndroid Build Coastguard Worker 1 << 20,
793*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
794*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
795*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
796*c8dee2aaSAndroid Build Coastguard Worker return;
797*c8dee2aaSAndroid Build Coastguard Worker }
798*c8dee2aaSAndroid Build Coastguard Worker }
799*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_InvalidOffset,reporter)800*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_InvalidOffset, reporter) {
801*c8dee2aaSAndroid Build Coastguard Worker { // offset isn't aligned
802*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[] {
803*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat4, 1, SkString{"var"}},
804*c8dee2aaSAndroid Build Coastguard Worker };
805*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
806*c8dee2aaSAndroid Build Coastguard Worker kAttributes,
807*c8dee2aaSAndroid Build Coastguard Worker 32,
808*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
809*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
810*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
811*c8dee2aaSAndroid Build Coastguard Worker return;
812*c8dee2aaSAndroid Build Coastguard Worker }
813*c8dee2aaSAndroid Build Coastguard Worker }
814*c8dee2aaSAndroid Build Coastguard Worker { // straddles stride boundary
815*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[] {
816*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat4, 0, SkString{"var"}},
817*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat2, 16, SkString{"var"}},
818*c8dee2aaSAndroid Build Coastguard Worker };
819*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
820*c8dee2aaSAndroid Build Coastguard Worker kAttributes,
821*c8dee2aaSAndroid Build Coastguard Worker 20,
822*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
823*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
824*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
825*c8dee2aaSAndroid Build Coastguard Worker return;
826*c8dee2aaSAndroid Build Coastguard Worker }
827*c8dee2aaSAndroid Build Coastguard Worker }
828*c8dee2aaSAndroid Build Coastguard Worker { // straddles stride boundary with attempt to overflow
829*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[] {
830*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat, std::numeric_limits<size_t>::max() - 3, SkString{"var"}},
831*c8dee2aaSAndroid Build Coastguard Worker };
832*c8dee2aaSAndroid Build Coastguard Worker if (!check_for_failure(reporter,
833*c8dee2aaSAndroid Build Coastguard Worker kAttributes,
834*c8dee2aaSAndroid Build Coastguard Worker 4,
835*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
836*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
837*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0])) {
838*c8dee2aaSAndroid Build Coastguard Worker return;
839*c8dee2aaSAndroid Build Coastguard Worker }
840*c8dee2aaSAndroid Build Coastguard Worker }
841*c8dee2aaSAndroid Build Coastguard Worker }
842*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_TooManyAttributes,reporter)843*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_TooManyAttributes, reporter) {
844*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kN = 500;
845*c8dee2aaSAndroid Build Coastguard Worker std::vector<Attribute> attrs;
846*c8dee2aaSAndroid Build Coastguard Worker attrs.reserve(kN);
847*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < kN; ++i) {
848*c8dee2aaSAndroid Build Coastguard Worker attrs.push_back({Attribute::Type::kFloat4, 0, SkStringPrintf("attr%zu", i)});
849*c8dee2aaSAndroid Build Coastguard Worker }
850*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
851*c8dee2aaSAndroid Build Coastguard Worker attrs,
852*c8dee2aaSAndroid Build Coastguard Worker 4*4,
853*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
854*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
855*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
856*c8dee2aaSAndroid Build Coastguard Worker }
857*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_TooManyVaryings,reporter)858*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_TooManyVaryings, reporter) {
859*c8dee2aaSAndroid Build Coastguard Worker static constexpr size_t kN = 500;
860*c8dee2aaSAndroid Build Coastguard Worker std::vector<Varying> varyings;
861*c8dee2aaSAndroid Build Coastguard Worker varyings.reserve(kN);
862*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < kN; ++i) {
863*c8dee2aaSAndroid Build Coastguard Worker varyings.push_back({Varying::Type::kFloat4, SkStringPrintf("varying%zu", i)});
864*c8dee2aaSAndroid Build Coastguard Worker }
865*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
866*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
867*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
868*c8dee2aaSAndroid Build Coastguard Worker SkSpan(varyings),
869*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
870*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
871*c8dee2aaSAndroid Build Coastguard Worker }
872*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_DuplicateAttributeNames,reporter)873*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_DuplicateAttributeNames, reporter) {
874*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[] {
875*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat4, 0, SkString{"var"}},
876*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat2, 16, SkString{"var"}}
877*c8dee2aaSAndroid Build Coastguard Worker };
878*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
879*c8dee2aaSAndroid Build Coastguard Worker kAttributes,
880*c8dee2aaSAndroid Build Coastguard Worker 24,
881*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
882*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
883*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
884*c8dee2aaSAndroid Build Coastguard Worker }
885*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_DuplicateVaryingNames,reporter)886*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_DuplicateVaryingNames, reporter) {
887*c8dee2aaSAndroid Build Coastguard Worker static const Varying kVaryings[] {
888*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat4, SkString{"var"}},
889*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat3, SkString{"var"}}
890*c8dee2aaSAndroid Build Coastguard Worker };
891*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
892*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
893*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
894*c8dee2aaSAndroid Build Coastguard Worker kVaryings,
895*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
896*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
897*c8dee2aaSAndroid Build Coastguard Worker }
898*c8dee2aaSAndroid Build Coastguard Worker
899*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* kSneakyName = "name; float3 sneaky";
900*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_SneakyExtraAttribute,reporter)901*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_SneakyExtraAttribute, reporter) {
902*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[] {
903*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat4, 0, SkString{kSneakyName}},
904*c8dee2aaSAndroid Build Coastguard Worker };
905*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
906*c8dee2aaSAndroid Build Coastguard Worker kAttributes,
907*c8dee2aaSAndroid Build Coastguard Worker 16,
908*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
909*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
910*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
911*c8dee2aaSAndroid Build Coastguard Worker }
912*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_SneakyExtraVarying,reporter)913*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_SneakyExtraVarying, reporter) {
914*c8dee2aaSAndroid Build Coastguard Worker static const Varying kVaryings[] {
915*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat4, SkString{kSneakyName}},
916*c8dee2aaSAndroid Build Coastguard Worker };
917*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
918*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
919*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
920*c8dee2aaSAndroid Build Coastguard Worker kVaryings,
921*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
922*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
923*c8dee2aaSAndroid Build Coastguard Worker }
924*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_AllowsFloat2PositionVarying,reporter)925*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_AllowsFloat2PositionVarying, reporter) {
926*c8dee2aaSAndroid Build Coastguard Worker // Position varying can be explicit if it is float2
927*c8dee2aaSAndroid Build Coastguard Worker static const Varying kVaryings[] {
928*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat2, SkString{"position"}},
929*c8dee2aaSAndroid Build Coastguard Worker };
930*c8dee2aaSAndroid Build Coastguard Worker check_for_success(reporter,
931*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
932*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
933*c8dee2aaSAndroid Build Coastguard Worker kVaryings,
934*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
935*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
936*c8dee2aaSAndroid Build Coastguard Worker }
937*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_InvalidPositionType,reporter)938*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_InvalidPositionType, reporter) {
939*c8dee2aaSAndroid Build Coastguard Worker // Position varying can be explicit but it must be float2
940*c8dee2aaSAndroid Build Coastguard Worker static const Varying kVaryings[] {
941*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat4, SkString{"position"}},
942*c8dee2aaSAndroid Build Coastguard Worker };
943*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
944*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
945*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
946*c8dee2aaSAndroid Build Coastguard Worker kVaryings,
947*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
948*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
949*c8dee2aaSAndroid Build Coastguard Worker }
950*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_EmptyAttributeName,reporter)951*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_EmptyAttributeName, reporter) {
952*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[] {
953*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat4, 0, SkString{}},
954*c8dee2aaSAndroid Build Coastguard Worker };
955*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
956*c8dee2aaSAndroid Build Coastguard Worker kAttributes,
957*c8dee2aaSAndroid Build Coastguard Worker 16,
958*c8dee2aaSAndroid Build Coastguard Worker kValidVaryings,
959*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
960*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
961*c8dee2aaSAndroid Build Coastguard Worker }
962*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpec_EmptyVaryingName,reporter)963*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpec_EmptyVaryingName, reporter) {
964*c8dee2aaSAndroid Build Coastguard Worker static const Varying kVaryings[] {
965*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat4, SkString{}},
966*c8dee2aaSAndroid Build Coastguard Worker };
967*c8dee2aaSAndroid Build Coastguard Worker check_for_failure(reporter,
968*c8dee2aaSAndroid Build Coastguard Worker kValidAttrs,
969*c8dee2aaSAndroid Build Coastguard Worker kValidStride,
970*c8dee2aaSAndroid Build Coastguard Worker kVaryings,
971*c8dee2aaSAndroid Build Coastguard Worker kValidVS,
972*c8dee2aaSAndroid Build Coastguard Worker kValidFSes[0]);
973*c8dee2aaSAndroid Build Coastguard Worker }
974*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpecVaryingPassthrough,reporter)975*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpecVaryingPassthrough, reporter) {
976*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[]{
977*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat2, 0, SkString{"position"}},
978*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat2, 8, SkString{"uv"} },
979*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kUByte4_unorm, 16, SkString{"color"} },
980*c8dee2aaSAndroid Build Coastguard Worker };
981*c8dee2aaSAndroid Build Coastguard Worker static const Varying kVaryings[]{
982*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat2, SkString{"position"}},
983*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat2, SkString{"uv"} },
984*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kHalf4, SkString{"color"} },
985*c8dee2aaSAndroid Build Coastguard Worker };
986*c8dee2aaSAndroid Build Coastguard Worker
987*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kVS[] = R"(
988*c8dee2aaSAndroid Build Coastguard Worker Varyings main(const Attributes a) {
989*c8dee2aaSAndroid Build Coastguard Worker Varyings v;
990*c8dee2aaSAndroid Build Coastguard Worker v.uv = a.uv;
991*c8dee2aaSAndroid Build Coastguard Worker v.position = a.position;
992*c8dee2aaSAndroid Build Coastguard Worker v.color = a.color;
993*c8dee2aaSAndroid Build Coastguard Worker return v;
994*c8dee2aaSAndroid Build Coastguard Worker }
995*c8dee2aaSAndroid Build Coastguard Worker )";
996*c8dee2aaSAndroid Build Coastguard Worker auto check = [&] (const char* fs, const char* passthroughAttr) {
997*c8dee2aaSAndroid Build Coastguard Worker auto [spec, error] = SkMeshSpecification::Make(kAttributes,
998*c8dee2aaSAndroid Build Coastguard Worker /*vertexStride=*/24,
999*c8dee2aaSAndroid Build Coastguard Worker kVaryings,
1000*c8dee2aaSAndroid Build Coastguard Worker SkString(kVS),
1001*c8dee2aaSAndroid Build Coastguard Worker SkString(fs));
1002*c8dee2aaSAndroid Build Coastguard Worker if (!spec) {
1003*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "%s\n%s", fs, error.c_str());
1004*c8dee2aaSAndroid Build Coastguard Worker return;
1005*c8dee2aaSAndroid Build Coastguard Worker }
1006*c8dee2aaSAndroid Build Coastguard Worker int idx = SkMeshSpecificationPriv::PassthroughLocalCoordsVaryingIndex(*spec);
1007*c8dee2aaSAndroid Build Coastguard Worker const SkString& actualAttr = idx >= 0 ? spec->attributes()[idx].name : SkString("<none>");
1008*c8dee2aaSAndroid Build Coastguard Worker if (!passthroughAttr) {
1009*c8dee2aaSAndroid Build Coastguard Worker if (idx >= 0) {
1010*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Expected no passthrough coords attribute, found %s.\n%s",
1011*c8dee2aaSAndroid Build Coastguard Worker actualAttr.c_str(),
1012*c8dee2aaSAndroid Build Coastguard Worker fs);
1013*c8dee2aaSAndroid Build Coastguard Worker }
1014*c8dee2aaSAndroid Build Coastguard Worker } else if (!actualAttr.equals(passthroughAttr)) {
1015*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "Expected %s as passthrough coords attribute, found %s.\n%s",
1016*c8dee2aaSAndroid Build Coastguard Worker passthroughAttr,
1017*c8dee2aaSAndroid Build Coastguard Worker actualAttr.c_str(),
1018*c8dee2aaSAndroid Build Coastguard Worker fs);
1019*c8dee2aaSAndroid Build Coastguard Worker }
1020*c8dee2aaSAndroid Build Coastguard Worker };
1021*c8dee2aaSAndroid Build Coastguard Worker
1022*c8dee2aaSAndroid Build Coastguard Worker // Simple
1023*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1024*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1025*c8dee2aaSAndroid Build Coastguard Worker })",
1026*c8dee2aaSAndroid Build Coastguard Worker "uv");
1027*c8dee2aaSAndroid Build Coastguard Worker
1028*c8dee2aaSAndroid Build Coastguard Worker // Simple, using position
1029*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1030*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1031*c8dee2aaSAndroid Build Coastguard Worker })",
1032*c8dee2aaSAndroid Build Coastguard Worker "position");
1033*c8dee2aaSAndroid Build Coastguard Worker
1034*c8dee2aaSAndroid Build Coastguard Worker // Simple, with output color
1035*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v, out half4 color) {
1036*c8dee2aaSAndroid Build Coastguard Worker color = v.color;
1037*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1038*c8dee2aaSAndroid Build Coastguard Worker })",
1039*c8dee2aaSAndroid Build Coastguard Worker "uv");
1040*c8dee2aaSAndroid Build Coastguard Worker
1041*c8dee2aaSAndroid Build Coastguard Worker // Three returns, all the same.
1042*c8dee2aaSAndroid Build Coastguard Worker check(R"(uniform int selector;
1043*c8dee2aaSAndroid Build Coastguard Worker
1044*c8dee2aaSAndroid Build Coastguard Worker float2 main(const Varyings v, out half4 color) {
1045*c8dee2aaSAndroid Build Coastguard Worker if (selector == 0) {
1046*c8dee2aaSAndroid Build Coastguard Worker color = half4(1, 0, 0, 1);
1047*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1048*c8dee2aaSAndroid Build Coastguard Worker }
1049*c8dee2aaSAndroid Build Coastguard Worker if (selector == 1) {
1050*c8dee2aaSAndroid Build Coastguard Worker color = half4(1, 1, 0, 1);
1051*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1052*c8dee2aaSAndroid Build Coastguard Worker }
1053*c8dee2aaSAndroid Build Coastguard Worker color = half4(1, 0, 1, 1);
1054*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1055*c8dee2aaSAndroid Build Coastguard Worker })",
1056*c8dee2aaSAndroid Build Coastguard Worker "position");
1057*c8dee2aaSAndroid Build Coastguard Worker
1058*c8dee2aaSAndroid Build Coastguard Worker // Three returns, one not like the others
1059*c8dee2aaSAndroid Build Coastguard Worker check(R"(uniform int selector;
1060*c8dee2aaSAndroid Build Coastguard Worker
1061*c8dee2aaSAndroid Build Coastguard Worker float2 main(const Varyings v, out half4 color) {
1062*c8dee2aaSAndroid Build Coastguard Worker if (selector == 0) {
1063*c8dee2aaSAndroid Build Coastguard Worker color = color.bgra;
1064*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1065*c8dee2aaSAndroid Build Coastguard Worker }
1066*c8dee2aaSAndroid Build Coastguard Worker if (selector == 1) {
1067*c8dee2aaSAndroid Build Coastguard Worker color = half4(1);
1068*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1069*c8dee2aaSAndroid Build Coastguard Worker }
1070*c8dee2aaSAndroid Build Coastguard Worker color = color;
1071*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1072*c8dee2aaSAndroid Build Coastguard Worker })",
1073*c8dee2aaSAndroid Build Coastguard Worker nullptr);
1074*c8dee2aaSAndroid Build Coastguard Worker
1075*c8dee2aaSAndroid Build Coastguard Worker // Swizzles aren't handled (yet?).
1076*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1077*c8dee2aaSAndroid Build Coastguard Worker return v.uv.yx;
1078*c8dee2aaSAndroid Build Coastguard Worker })",
1079*c8dee2aaSAndroid Build Coastguard Worker nullptr);
1080*c8dee2aaSAndroid Build Coastguard Worker
1081*c8dee2aaSAndroid Build Coastguard Worker // Return from non-main fools us?
1082*c8dee2aaSAndroid Build Coastguard Worker check(R"(noinline half4 get_color(const Varyings v) { return v.color; }
1083*c8dee2aaSAndroid Build Coastguard Worker
1084*c8dee2aaSAndroid Build Coastguard Worker float2 main(const Varyings v, out half4 color) {
1085*c8dee2aaSAndroid Build Coastguard Worker color = get_color(v);
1086*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1087*c8dee2aaSAndroid Build Coastguard Worker })",
1088*c8dee2aaSAndroid Build Coastguard Worker "position");
1089*c8dee2aaSAndroid Build Coastguard Worker }
1090*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(MeshSpecUnusedVaryings,reporter)1091*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(MeshSpecUnusedVaryings, reporter) {
1092*c8dee2aaSAndroid Build Coastguard Worker static const Attribute kAttributes[]{
1093*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat2, 0, SkString{"position"}},
1094*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kFloat2, 8, SkString{"uv"} },
1095*c8dee2aaSAndroid Build Coastguard Worker {Attribute::Type::kUByte4_unorm, 16, SkString{"color"} },
1096*c8dee2aaSAndroid Build Coastguard Worker };
1097*c8dee2aaSAndroid Build Coastguard Worker static const Varying kVaryings[]{
1098*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat2, SkString{"position"}},
1099*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kFloat2, SkString{"uv"} },
1100*c8dee2aaSAndroid Build Coastguard Worker {Varying::Type::kHalf4, SkString{"color"} },
1101*c8dee2aaSAndroid Build Coastguard Worker };
1102*c8dee2aaSAndroid Build Coastguard Worker
1103*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kVS[] = R"(
1104*c8dee2aaSAndroid Build Coastguard Worker Varyings main(const Attributes a) {
1105*c8dee2aaSAndroid Build Coastguard Worker Varyings v;
1106*c8dee2aaSAndroid Build Coastguard Worker v.uv = a.uv;
1107*c8dee2aaSAndroid Build Coastguard Worker v.position = a.position;
1108*c8dee2aaSAndroid Build Coastguard Worker v.color = a.color;
1109*c8dee2aaSAndroid Build Coastguard Worker return v;
1110*c8dee2aaSAndroid Build Coastguard Worker }
1111*c8dee2aaSAndroid Build Coastguard Worker )";
1112*c8dee2aaSAndroid Build Coastguard Worker
1113*c8dee2aaSAndroid Build Coastguard Worker auto check = [&](const char* fs, bool positionDead, bool uvDead, bool colorDead) {
1114*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::size(kVaryings) == 3);
1115*c8dee2aaSAndroid Build Coastguard Worker auto [spec, error] = SkMeshSpecification::Make(kAttributes,
1116*c8dee2aaSAndroid Build Coastguard Worker /*vertexStride=*/24,
1117*c8dee2aaSAndroid Build Coastguard Worker kVaryings,
1118*c8dee2aaSAndroid Build Coastguard Worker SkString(kVS),
1119*c8dee2aaSAndroid Build Coastguard Worker SkString(fs));
1120*c8dee2aaSAndroid Build Coastguard Worker if (!spec) {
1121*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "%s\n%s", fs, error.c_str());
1122*c8dee2aaSAndroid Build Coastguard Worker return;
1123*c8dee2aaSAndroid Build Coastguard Worker }
1124*c8dee2aaSAndroid Build Coastguard Worker bool positionActuallyDead = SkMeshSpecificationPriv::VaryingIsDead(*spec, 0);
1125*c8dee2aaSAndroid Build Coastguard Worker bool uvActuallyDead = SkMeshSpecificationPriv::VaryingIsDead(*spec, 1);
1126*c8dee2aaSAndroid Build Coastguard Worker bool colorActuallyDead = SkMeshSpecificationPriv::VaryingIsDead(*spec, 2);
1127*c8dee2aaSAndroid Build Coastguard Worker auto str = [](bool dead) { return dead ? "dead" : "not dead"; };
1128*c8dee2aaSAndroid Build Coastguard Worker if (positionActuallyDead != positionDead) {
1129*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
1130*c8dee2aaSAndroid Build Coastguard Worker "Expected position to be detected %s but it is detected %s.\n%s",
1131*c8dee2aaSAndroid Build Coastguard Worker str(positionDead),
1132*c8dee2aaSAndroid Build Coastguard Worker str(positionActuallyDead),
1133*c8dee2aaSAndroid Build Coastguard Worker fs);
1134*c8dee2aaSAndroid Build Coastguard Worker }
1135*c8dee2aaSAndroid Build Coastguard Worker if (uvActuallyDead != uvDead) {
1136*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
1137*c8dee2aaSAndroid Build Coastguard Worker "Expected uv to be detected %s but it is detected %s.\n%s",
1138*c8dee2aaSAndroid Build Coastguard Worker str(uvDead),
1139*c8dee2aaSAndroid Build Coastguard Worker str(uvActuallyDead),
1140*c8dee2aaSAndroid Build Coastguard Worker fs);
1141*c8dee2aaSAndroid Build Coastguard Worker }
1142*c8dee2aaSAndroid Build Coastguard Worker if (colorActuallyDead != colorDead) {
1143*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter,
1144*c8dee2aaSAndroid Build Coastguard Worker "Expected color to be detected %s but it is detected %s.\n%s",
1145*c8dee2aaSAndroid Build Coastguard Worker str(colorDead),
1146*c8dee2aaSAndroid Build Coastguard Worker str(colorActuallyDead),
1147*c8dee2aaSAndroid Build Coastguard Worker fs);
1148*c8dee2aaSAndroid Build Coastguard Worker }
1149*c8dee2aaSAndroid Build Coastguard Worker };
1150*c8dee2aaSAndroid Build Coastguard Worker
1151*c8dee2aaSAndroid Build Coastguard Worker // Simple
1152*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1153*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1154*c8dee2aaSAndroid Build Coastguard Worker })",
1155*c8dee2aaSAndroid Build Coastguard Worker true,
1156*c8dee2aaSAndroid Build Coastguard Worker true,
1157*c8dee2aaSAndroid Build Coastguard Worker true);
1158*c8dee2aaSAndroid Build Coastguard Worker
1159*c8dee2aaSAndroid Build Coastguard Worker // Simple, using position
1160*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1161*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1162*c8dee2aaSAndroid Build Coastguard Worker })",
1163*c8dee2aaSAndroid Build Coastguard Worker true,
1164*c8dee2aaSAndroid Build Coastguard Worker true,
1165*c8dee2aaSAndroid Build Coastguard Worker true);
1166*c8dee2aaSAndroid Build Coastguard Worker
1167*c8dee2aaSAndroid Build Coastguard Worker // Two returns that are both passthrough of the same varying
1168*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v, out half4 color) {
1169*c8dee2aaSAndroid Build Coastguard Worker if (v.color.r > 0.5) {
1170*c8dee2aaSAndroid Build Coastguard Worker color = v.color;
1171*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1172*c8dee2aaSAndroid Build Coastguard Worker } else {
1173*c8dee2aaSAndroid Build Coastguard Worker color = 2*color;
1174*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1175*c8dee2aaSAndroid Build Coastguard Worker }
1176*c8dee2aaSAndroid Build Coastguard Worker })",
1177*c8dee2aaSAndroid Build Coastguard Worker true,
1178*c8dee2aaSAndroid Build Coastguard Worker true,
1179*c8dee2aaSAndroid Build Coastguard Worker false);
1180*c8dee2aaSAndroid Build Coastguard Worker
1181*c8dee2aaSAndroid Build Coastguard Worker // Two returns that are both passthrough of the different varyings and unused other varying
1182*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v, out half4 color) {
1183*c8dee2aaSAndroid Build Coastguard Worker if (v.position.x > 10) {
1184*c8dee2aaSAndroid Build Coastguard Worker color = half4(0);
1185*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1186*c8dee2aaSAndroid Build Coastguard Worker } else {
1187*c8dee2aaSAndroid Build Coastguard Worker color = half4(1);
1188*c8dee2aaSAndroid Build Coastguard Worker return v.position;
1189*c8dee2aaSAndroid Build Coastguard Worker }
1190*c8dee2aaSAndroid Build Coastguard Worker })",
1191*c8dee2aaSAndroid Build Coastguard Worker false,
1192*c8dee2aaSAndroid Build Coastguard Worker false,
1193*c8dee2aaSAndroid Build Coastguard Worker true);
1194*c8dee2aaSAndroid Build Coastguard Worker
1195*c8dee2aaSAndroid Build Coastguard Worker // Passthrough but we also use the varying elsewhere
1196*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v, out half4 color) {
1197*c8dee2aaSAndroid Build Coastguard Worker color = half4(v.uv.x, 0, 0, 1);
1198*c8dee2aaSAndroid Build Coastguard Worker return v.uv;
1199*c8dee2aaSAndroid Build Coastguard Worker })",
1200*c8dee2aaSAndroid Build Coastguard Worker true,
1201*c8dee2aaSAndroid Build Coastguard Worker false,
1202*c8dee2aaSAndroid Build Coastguard Worker true);
1203*c8dee2aaSAndroid Build Coastguard Worker
1204*c8dee2aaSAndroid Build Coastguard Worker // Use two varyings is a return statement
1205*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1206*c8dee2aaSAndroid Build Coastguard Worker return v.uv + v.position;
1207*c8dee2aaSAndroid Build Coastguard Worker })",
1208*c8dee2aaSAndroid Build Coastguard Worker false,
1209*c8dee2aaSAndroid Build Coastguard Worker false,
1210*c8dee2aaSAndroid Build Coastguard Worker true);
1211*c8dee2aaSAndroid Build Coastguard Worker
1212*c8dee2aaSAndroid Build Coastguard Worker // Slightly more complicated varying use.
1213*c8dee2aaSAndroid Build Coastguard Worker check(R"(noinline vec2 get_pos(const Varyings v) { return v.position; }
1214*c8dee2aaSAndroid Build Coastguard Worker
1215*c8dee2aaSAndroid Build Coastguard Worker noinline half4 identity(half4 c) { return c; }
1216*c8dee2aaSAndroid Build Coastguard Worker
1217*c8dee2aaSAndroid Build Coastguard Worker float2 main(const Varyings v, out half4 color) {
1218*c8dee2aaSAndroid Build Coastguard Worker color = identity(v.color);
1219*c8dee2aaSAndroid Build Coastguard Worker return v.uv + get_pos(v);
1220*c8dee2aaSAndroid Build Coastguard Worker })",
1221*c8dee2aaSAndroid Build Coastguard Worker false,
1222*c8dee2aaSAndroid Build Coastguard Worker false,
1223*c8dee2aaSAndroid Build Coastguard Worker false);
1224*c8dee2aaSAndroid Build Coastguard Worker
1225*c8dee2aaSAndroid Build Coastguard Worker // Go through assignment to another Varyings.
1226*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1227*c8dee2aaSAndroid Build Coastguard Worker Varyings otherVaryings;
1228*c8dee2aaSAndroid Build Coastguard Worker otherVaryings = v;
1229*c8dee2aaSAndroid Build Coastguard Worker return otherVaryings.uv;
1230*c8dee2aaSAndroid Build Coastguard Worker })",
1231*c8dee2aaSAndroid Build Coastguard Worker true,
1232*c8dee2aaSAndroid Build Coastguard Worker false,
1233*c8dee2aaSAndroid Build Coastguard Worker true);
1234*c8dee2aaSAndroid Build Coastguard Worker
1235*c8dee2aaSAndroid Build Coastguard Worker // We're not very smart. We just look for any use of the field in any Varyings value and don't
1236*c8dee2aaSAndroid Build Coastguard Worker // do any data flow analysis.
1237*c8dee2aaSAndroid Build Coastguard Worker check(R"(float2 main(const Varyings v) {
1238*c8dee2aaSAndroid Build Coastguard Worker Varyings otherVaryings;
1239*c8dee2aaSAndroid Build Coastguard Worker otherVaryings.uv = half2(5);
1240*c8dee2aaSAndroid Build Coastguard Worker otherVaryings.position = half2(10);
1241*c8dee2aaSAndroid Build Coastguard Worker return otherVaryings.position;
1242*c8dee2aaSAndroid Build Coastguard Worker })",
1243*c8dee2aaSAndroid Build Coastguard Worker false,
1244*c8dee2aaSAndroid Build Coastguard Worker false,
1245*c8dee2aaSAndroid Build Coastguard Worker true);
1246*c8dee2aaSAndroid Build Coastguard Worker }
1247