xref: /third_party/skia/tests/ProgramsTest.cpp (revision cb93a386)
1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci// This is a GPU-backend specific test.
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
13cb93a386Sopenharmony_ci#include "include/private/SkChecksum.h"
14cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
15cb93a386Sopenharmony_ci#include "src/gpu/GrAutoLocaleSetter.h"
16cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrDrawOpTest.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrDrawingManager.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h"
22cb93a386Sopenharmony_ci#include "src/gpu/GrXferProcessor.h"
23cb93a386Sopenharmony_ci#include "src/gpu/effects/GrBlendFragmentProcessor.h"
24cb93a386Sopenharmony_ci#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
25cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
26cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
27cb93a386Sopenharmony_ci#include "src/gpu/ops/GrDrawOp.h"
28cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h"
29cb93a386Sopenharmony_ci#include "tests/Test.h"
30cb93a386Sopenharmony_ci#include "tools/gpu/GrContextFactory.h"
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci#ifdef SK_GL
33cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLGpu.h"
34cb93a386Sopenharmony_ci#endif
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_ci/*
37cb93a386Sopenharmony_ci * A simple processor which just tries to insert a massive key and verify that it can retrieve the
38cb93a386Sopenharmony_ci * whole thing correctly
39cb93a386Sopenharmony_ci */
40cb93a386Sopenharmony_cistatic const uint32_t kMaxKeySize = 1024;
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_cinamespace {
43cb93a386Sopenharmony_ciclass BigKeyProcessor : public GrFragmentProcessor {
44cb93a386Sopenharmony_cipublic:
45cb93a386Sopenharmony_ci    static std::unique_ptr<GrFragmentProcessor> Make() {
46cb93a386Sopenharmony_ci        return std::unique_ptr<GrFragmentProcessor>(new BigKeyProcessor);
47cb93a386Sopenharmony_ci    }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    const char* name() const override { return "Big_Ole_Key"; }
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci    std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
52cb93a386Sopenharmony_ci        class Impl : public ProgramImpl {
53cb93a386Sopenharmony_ci        public:
54cb93a386Sopenharmony_ci            void emitCode(EmitArgs& args) override {
55cb93a386Sopenharmony_ci                args.fFragBuilder->codeAppendf("return half4(1);\n");
56cb93a386Sopenharmony_ci            }
57cb93a386Sopenharmony_ci        };
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci        return std::make_unique<Impl>();
60cb93a386Sopenharmony_ci    }
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci    std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(); }
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ciprivate:
65cb93a386Sopenharmony_ci    BigKeyProcessor() : INHERITED(kBigKeyProcessor_ClassID, kNone_OptimizationFlags) {}
66cb93a386Sopenharmony_ci    void onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
67cb93a386Sopenharmony_ci        for (uint32_t i = 0; i < kMaxKeySize; i++) {
68cb93a386Sopenharmony_ci            b->add32(i);
69cb93a386Sopenharmony_ci        }
70cb93a386Sopenharmony_ci    }
71cb93a386Sopenharmony_ci    bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    using INHERITED = GrFragmentProcessor;
76cb93a386Sopenharmony_ci};
77cb93a386Sopenharmony_ci}  // anonymous namespace
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ciGR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor);
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci#if GR_TEST_UTILS
82cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> BigKeyProcessor::TestCreate(GrProcessorTestData*) {
83cb93a386Sopenharmony_ci    return BigKeyProcessor::Make();
84cb93a386Sopenharmony_ci}
85cb93a386Sopenharmony_ci#endif
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ciclass BlockInputFragmentProcessor : public GrFragmentProcessor {
90cb93a386Sopenharmony_cipublic:
91cb93a386Sopenharmony_ci    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp) {
92cb93a386Sopenharmony_ci        return std::unique_ptr<GrFragmentProcessor>(new BlockInputFragmentProcessor(std::move(fp)));
93cb93a386Sopenharmony_ci    }
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci    const char* name() const override { return "Block_Input"; }
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci    std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
98cb93a386Sopenharmony_ci        return std::make_unique<GLFP>();
99cb93a386Sopenharmony_ci    }
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    std::unique_ptr<GrFragmentProcessor> clone() const override {
102cb93a386Sopenharmony_ci        return Make(this->childProcessor(0)->clone());
103cb93a386Sopenharmony_ci    }
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ciprivate:
106cb93a386Sopenharmony_ci    class GLFP : public ProgramImpl {
107cb93a386Sopenharmony_ci    public:
108cb93a386Sopenharmony_ci        void emitCode(EmitArgs& args) override {
109cb93a386Sopenharmony_ci            SkString temp = this->invokeChild(0, args);
110cb93a386Sopenharmony_ci            args.fFragBuilder->codeAppendf("return %s;", temp.c_str());
111cb93a386Sopenharmony_ci        }
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    private:
114cb93a386Sopenharmony_ci        using INHERITED = ProgramImpl;
115cb93a386Sopenharmony_ci    };
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child)
118cb93a386Sopenharmony_ci            : INHERITED(kBlockInputFragmentProcessor_ClassID, kNone_OptimizationFlags) {
119cb93a386Sopenharmony_ci        this->registerChild(std::move(child));
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    using INHERITED = GrFragmentProcessor;
127cb93a386Sopenharmony_ci};
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci/*
132cb93a386Sopenharmony_ci * Begin test code
133cb93a386Sopenharmony_ci */
134cb93a386Sopenharmony_cistatic const int kRenderTargetHeight = 1;
135cb93a386Sopenharmony_cistatic const int kRenderTargetWidth = 1;
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_cistatic std::unique_ptr<skgpu::v1::SurfaceDrawContext> random_surface_draw_context(
138cb93a386Sopenharmony_ci        GrRecordingContext* rContext,
139cb93a386Sopenharmony_ci        SkRandom* random,
140cb93a386Sopenharmony_ci        const GrCaps* caps) {
141cb93a386Sopenharmony_ci    GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin
142cb93a386Sopenharmony_ci                                                : kBottomLeft_GrSurfaceOrigin;
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci    GrColorType ct = GrColorType::kRGBA_8888;
145cb93a386Sopenharmony_ci    const GrBackendFormat format = caps->getDefaultBackendFormat(ct, GrRenderable::kYes);
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci    int sampleCnt = random->nextBool() ? caps->getRenderTargetSampleCount(2, format) : 1;
148cb93a386Sopenharmony_ci    // Above could be 0 if msaa isn't supported.
149cb93a386Sopenharmony_ci    sampleCnt = std::max(1, sampleCnt);
150cb93a386Sopenharmony_ci
151cb93a386Sopenharmony_ci    return skgpu::v1::SurfaceDrawContext::Make(
152cb93a386Sopenharmony_ci            rContext, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
153cb93a386Sopenharmony_ci            {kRenderTargetWidth, kRenderTargetHeight}, SkSurfaceProps(), sampleCnt,
154cb93a386Sopenharmony_ci            GrMipmapped::kNo, GrProtected::kNo, origin);
155cb93a386Sopenharmony_ci}
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci#if GR_TEST_UTILS
158cb93a386Sopenharmony_cistatic void set_random_xpf(GrPaint* paint, GrProcessorTestData* d) {
159cb93a386Sopenharmony_ci    paint->setXPFactory(GrXPFactoryTestFactory::Get(d));
160cb93a386Sopenharmony_ci}
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_cistatic std::unique_ptr<GrFragmentProcessor> create_random_proc_tree(GrProcessorTestData* d,
163cb93a386Sopenharmony_ci                                                                    int minLevels, int maxLevels) {
164cb93a386Sopenharmony_ci    SkASSERT(1 <= minLevels);
165cb93a386Sopenharmony_ci    SkASSERT(minLevels <= maxLevels);
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_ci    // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate.
168cb93a386Sopenharmony_ci    // If returning a leaf node, make sure that it doesn't have children (e.g. another
169cb93a386Sopenharmony_ci    // GrComposeEffect)
170cb93a386Sopenharmony_ci    const float terminateProbability = 0.3f;
171cb93a386Sopenharmony_ci    if (1 == minLevels) {
172cb93a386Sopenharmony_ci        bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability);
173cb93a386Sopenharmony_ci        if (terminate) {
174cb93a386Sopenharmony_ci            std::unique_ptr<GrFragmentProcessor> fp;
175cb93a386Sopenharmony_ci            while (true) {
176cb93a386Sopenharmony_ci                fp = GrFragmentProcessorTestFactory::Make(d);
177cb93a386Sopenharmony_ci                if (!fp) {
178cb93a386Sopenharmony_ci                    return nullptr;
179cb93a386Sopenharmony_ci                }
180cb93a386Sopenharmony_ci                if (0 == fp->numNonNullChildProcessors()) {
181cb93a386Sopenharmony_ci                    break;
182cb93a386Sopenharmony_ci                }
183cb93a386Sopenharmony_ci            }
184cb93a386Sopenharmony_ci            return fp;
185cb93a386Sopenharmony_ci        }
186cb93a386Sopenharmony_ci    }
187cb93a386Sopenharmony_ci    // If we didn't terminate, choose either the left or right subtree to fulfill
188cb93a386Sopenharmony_ci    // the minLevels requirement of this tree; the other child can have as few levels as it wants.
189cb93a386Sopenharmony_ci    // Also choose a random xfer mode.
190cb93a386Sopenharmony_ci    if (minLevels > 1) {
191cb93a386Sopenharmony_ci        --minLevels;
192cb93a386Sopenharmony_ci    }
193cb93a386Sopenharmony_ci    auto minLevelsChild = create_random_proc_tree(d, minLevels, maxLevels - 1);
194cb93a386Sopenharmony_ci    std::unique_ptr<GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, maxLevels - 1));
195cb93a386Sopenharmony_ci    if (!minLevelsChild || !otherChild) {
196cb93a386Sopenharmony_ci        return nullptr;
197cb93a386Sopenharmony_ci    }
198cb93a386Sopenharmony_ci    SkBlendMode mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0,
199cb93a386Sopenharmony_ci                                                               (int)SkBlendMode::kLastMode));
200cb93a386Sopenharmony_ci    std::unique_ptr<GrFragmentProcessor> fp;
201cb93a386Sopenharmony_ci    if (d->fRandom->nextF() < 0.5f) {
202cb93a386Sopenharmony_ci        fp = GrBlendFragmentProcessor::Make(std::move(minLevelsChild), std::move(otherChild), mode);
203cb93a386Sopenharmony_ci        SkASSERT(fp);
204cb93a386Sopenharmony_ci    } else {
205cb93a386Sopenharmony_ci        fp = GrBlendFragmentProcessor::Make(std::move(otherChild), std::move(minLevelsChild), mode);
206cb93a386Sopenharmony_ci        SkASSERT(fp);
207cb93a386Sopenharmony_ci    }
208cb93a386Sopenharmony_ci    return fp;
209cb93a386Sopenharmony_ci}
210cb93a386Sopenharmony_ci
211cb93a386Sopenharmony_cistatic void set_random_color_coverage_stages(GrPaint* paint,
212cb93a386Sopenharmony_ci                                             GrProcessorTestData* d,
213cb93a386Sopenharmony_ci                                             int maxStages,
214cb93a386Sopenharmony_ci                                             int maxTreeLevels) {
215cb93a386Sopenharmony_ci    // Randomly choose to either create a linear pipeline of procs or create one proc tree
216cb93a386Sopenharmony_ci    const float procTreeProbability = 0.5f;
217cb93a386Sopenharmony_ci    if (d->fRandom->nextF() < procTreeProbability) {
218cb93a386Sopenharmony_ci        std::unique_ptr<GrFragmentProcessor> fp(create_random_proc_tree(d, 2, maxTreeLevels));
219cb93a386Sopenharmony_ci        if (fp) {
220cb93a386Sopenharmony_ci            paint->setColorFragmentProcessor(std::move(fp));
221cb93a386Sopenharmony_ci        }
222cb93a386Sopenharmony_ci    } else {
223cb93a386Sopenharmony_ci        if (maxStages >= 1) {
224cb93a386Sopenharmony_ci            if (std::unique_ptr<GrFragmentProcessor> fp = GrFragmentProcessorTestFactory::Make(d)) {
225cb93a386Sopenharmony_ci                paint->setColorFragmentProcessor(std::move(fp));
226cb93a386Sopenharmony_ci            }
227cb93a386Sopenharmony_ci        }
228cb93a386Sopenharmony_ci        if (maxStages >= 2) {
229cb93a386Sopenharmony_ci            if (std::unique_ptr<GrFragmentProcessor> fp = GrFragmentProcessorTestFactory::Make(d)) {
230cb93a386Sopenharmony_ci                paint->setCoverageFragmentProcessor(std::move(fp));
231cb93a386Sopenharmony_ci            }
232cb93a386Sopenharmony_ci        }
233cb93a386Sopenharmony_ci    }
234cb93a386Sopenharmony_ci}
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_ci#endif
237cb93a386Sopenharmony_ci
238cb93a386Sopenharmony_ci#if !GR_TEST_UTILS
239cb93a386Sopenharmony_cibool GrDrawingManager::ProgramUnitTest(GrDirectContext*, int) { return true; }
240cb93a386Sopenharmony_ci#else
241cb93a386Sopenharmony_cibool GrDrawingManager::ProgramUnitTest(GrDirectContext* direct, int maxStages, int maxLevels) {
242cb93a386Sopenharmony_ci    GrProxyProvider* proxyProvider = direct->priv().proxyProvider();
243cb93a386Sopenharmony_ci    const GrCaps* caps = direct->priv().caps();
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_ci    GrProcessorTestData::ViewInfo views[2];
246cb93a386Sopenharmony_ci
247cb93a386Sopenharmony_ci    // setup arbitrary textures
248cb93a386Sopenharmony_ci    GrMipmapped mipMapped = GrMipmapped(caps->mipmapSupport());
249cb93a386Sopenharmony_ci    {
250cb93a386Sopenharmony_ci        static constexpr SkISize kDims = {34, 18};
251cb93a386Sopenharmony_ci        const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
252cb93a386Sopenharmony_ci                                                                     GrRenderable::kYes);
253cb93a386Sopenharmony_ci        auto proxy = proxyProvider->createProxy(format, kDims, GrRenderable::kYes, 1,
254cb93a386Sopenharmony_ci                                                mipMapped, SkBackingFit::kExact, SkBudgeted::kNo,
255cb93a386Sopenharmony_ci                                                GrProtected::kNo, GrInternalSurfaceFlags::kNone);
256cb93a386Sopenharmony_ci        GrSwizzle swizzle = caps->getReadSwizzle(format, GrColorType::kRGBA_8888);
257cb93a386Sopenharmony_ci        views[0] = {{std::move(proxy), kBottomLeft_GrSurfaceOrigin, swizzle},
258cb93a386Sopenharmony_ci                    GrColorType::kRGBA_8888, kPremul_SkAlphaType};
259cb93a386Sopenharmony_ci    }
260cb93a386Sopenharmony_ci    {
261cb93a386Sopenharmony_ci        static constexpr SkISize kDims = {16, 22};
262cb93a386Sopenharmony_ci        const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8,
263cb93a386Sopenharmony_ci                                                                     GrRenderable::kNo);
264cb93a386Sopenharmony_ci        auto proxy = proxyProvider->createProxy(format, kDims, GrRenderable::kNo, 1, mipMapped,
265cb93a386Sopenharmony_ci                                                SkBackingFit::kExact, SkBudgeted::kNo,
266cb93a386Sopenharmony_ci                                                GrProtected::kNo, GrInternalSurfaceFlags::kNone);
267cb93a386Sopenharmony_ci        GrSwizzle swizzle = caps->getReadSwizzle(format, GrColorType::kAlpha_8);
268cb93a386Sopenharmony_ci        views[1] = {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle},
269cb93a386Sopenharmony_ci                      GrColorType::kAlpha_8, kPremul_SkAlphaType};
270cb93a386Sopenharmony_ci    }
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci    if (!std::get<0>(views[0]) || !std::get<0>(views[1])) {
273cb93a386Sopenharmony_ci        SkDebugf("Could not allocate textures for test");
274cb93a386Sopenharmony_ci        return false;
275cb93a386Sopenharmony_ci    }
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci    SkRandom random;
278cb93a386Sopenharmony_ci    static const int NUM_TESTS = 1024;
279cb93a386Sopenharmony_ci    for (int t = 0; t < NUM_TESTS; t++) {
280cb93a386Sopenharmony_ci        // setup random render target(can fail)
281cb93a386Sopenharmony_ci        auto surfaceDrawContext = random_surface_draw_context(direct, &random, caps);
282cb93a386Sopenharmony_ci        if (!surfaceDrawContext) {
283cb93a386Sopenharmony_ci            SkDebugf("Could not allocate surfaceDrawContext");
284cb93a386Sopenharmony_ci            return false;
285cb93a386Sopenharmony_ci        }
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci        GrPaint paint;
288cb93a386Sopenharmony_ci        GrProcessorTestData ptd(&random, direct, /*maxTreeDepth=*/1, SK_ARRAY_COUNT(views), views);
289cb93a386Sopenharmony_ci        set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels);
290cb93a386Sopenharmony_ci        set_random_xpf(&paint, &ptd);
291cb93a386Sopenharmony_ci        GrDrawRandomOp(&random, surfaceDrawContext.get(), std::move(paint));
292cb93a386Sopenharmony_ci    }
293cb93a386Sopenharmony_ci    // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
294cb93a386Sopenharmony_ci    direct->flush(GrFlushInfo());
295cb93a386Sopenharmony_ci    direct->submit(false);
296cb93a386Sopenharmony_ci
297cb93a386Sopenharmony_ci    // Validate that GrFPs work correctly without an input.
298cb93a386Sopenharmony_ci    auto sdc = skgpu::v1::SurfaceDrawContext::Make(
299cb93a386Sopenharmony_ci            direct, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
300cb93a386Sopenharmony_ci            {kRenderTargetWidth, kRenderTargetHeight}, SkSurfaceProps());
301cb93a386Sopenharmony_ci    if (!sdc) {
302cb93a386Sopenharmony_ci        SkDebugf("Could not allocate a surfaceDrawContext");
303cb93a386Sopenharmony_ci        return false;
304cb93a386Sopenharmony_ci    }
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    int fpFactoryCnt = GrFragmentProcessorTestFactory::Count();
307cb93a386Sopenharmony_ci    for (int i = 0; i < fpFactoryCnt; ++i) {
308cb93a386Sopenharmony_ci        // Since FP factories internally randomize, call each 10 times.
309cb93a386Sopenharmony_ci        for (int j = 0; j < 10; ++j) {
310cb93a386Sopenharmony_ci            GrProcessorTestData ptd(&random, direct, /*maxTreeDepth=*/1, SK_ARRAY_COUNT(views),
311cb93a386Sopenharmony_ci                                    views);
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_ci            GrPaint paint;
314cb93a386Sopenharmony_ci            paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
315cb93a386Sopenharmony_ci            auto fp = GrFragmentProcessorTestFactory::MakeIdx(i, &ptd);
316cb93a386Sopenharmony_ci            auto blockFP = BlockInputFragmentProcessor::Make(std::move(fp));
317cb93a386Sopenharmony_ci            paint.setColorFragmentProcessor(std::move(blockFP));
318cb93a386Sopenharmony_ci            GrDrawRandomOp(&random, sdc.get(), std::move(paint));
319cb93a386Sopenharmony_ci
320cb93a386Sopenharmony_ci            direct->flush(GrFlushInfo());
321cb93a386Sopenharmony_ci            direct->submit(false);
322cb93a386Sopenharmony_ci        }
323cb93a386Sopenharmony_ci    }
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci    return true;
326cb93a386Sopenharmony_ci}
327cb93a386Sopenharmony_ci#endif
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_cistatic int get_programs_max_stages(const sk_gpu_test::ContextInfo& ctxInfo) {
330cb93a386Sopenharmony_ci    int maxStages = 6;
331cb93a386Sopenharmony_ci#ifdef SK_GL
332cb93a386Sopenharmony_ci    auto context = ctxInfo.directContext();
333cb93a386Sopenharmony_ci    if (skiatest::IsGLContextType(ctxInfo.type())) {
334cb93a386Sopenharmony_ci        GrGLGpu* gpu = static_cast<GrGLGpu*>(context->priv().getGpu());
335cb93a386Sopenharmony_ci        if (kGLES_GrGLStandard == gpu->glStandard()) {
336cb93a386Sopenharmony_ci        // We've had issues with driver crashes and HW limits being exceeded with many effects on
337cb93a386Sopenharmony_ci        // Android devices. We have passes on ARM devices with the default number of stages.
338cb93a386Sopenharmony_ci        // TODO When we run ES 3.00 GLSL in more places, test again
339cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID
340cb93a386Sopenharmony_ci        if (gpu->ctxInfo().vendor() != GrGLVendor::kARM) {
341cb93a386Sopenharmony_ci            maxStages = 1;
342cb93a386Sopenharmony_ci        }
343cb93a386Sopenharmony_ci#endif
344cb93a386Sopenharmony_ci        // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
345cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS
346cb93a386Sopenharmony_ci            maxStages = 3;
347cb93a386Sopenharmony_ci#endif
348cb93a386Sopenharmony_ci        }
349cb93a386Sopenharmony_ci        // On Angle D3D we will hit a limit of out variables if we use too many stages. This is
350cb93a386Sopenharmony_ci        // particularly true on D3D9 with a low limit on varyings and the fact that every varying is
351cb93a386Sopenharmony_ci        // packed as though it has 4 components.
352cb93a386Sopenharmony_ci        if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType) {
353cb93a386Sopenharmony_ci            maxStages = 2;
354cb93a386Sopenharmony_ci        } else if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
355cb93a386Sopenharmony_ci            maxStages = 3;
356cb93a386Sopenharmony_ci        }
357cb93a386Sopenharmony_ci    }
358cb93a386Sopenharmony_ci#endif
359cb93a386Sopenharmony_ci    return maxStages;
360cb93a386Sopenharmony_ci}
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_cistatic int get_programs_max_levels(const sk_gpu_test::ContextInfo& ctxInfo) {
363cb93a386Sopenharmony_ci    // A full tree with 5 levels (31 nodes) may cause a program that exceeds shader limits
364cb93a386Sopenharmony_ci    // (e.g. uniform or varying limits); maxTreeLevels should be a number from 1 to 4 inclusive.
365cb93a386Sopenharmony_ci    int maxTreeLevels = 4;
366cb93a386Sopenharmony_ci    if (skiatest::IsGLContextType(ctxInfo.type())) {
367cb93a386Sopenharmony_ci        // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
368cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS
369cb93a386Sopenharmony_ci        maxTreeLevels = 2;
370cb93a386Sopenharmony_ci#endif
371cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_ANDROID) && defined(SK_GL)
372cb93a386Sopenharmony_ci        GrGLGpu* gpu = static_cast<GrGLGpu*>(ctxInfo.directContext()->priv().getGpu());
373cb93a386Sopenharmony_ci        // Tecno Spark 3 Pro with Power VR Rogue GE8300 will fail shader compiles with
374cb93a386Sopenharmony_ci        // no message if the shader is particularly long.
375cb93a386Sopenharmony_ci        if (gpu->ctxInfo().vendor() == GrGLVendor::kImagination) {
376cb93a386Sopenharmony_ci            maxTreeLevels = 3;
377cb93a386Sopenharmony_ci        }
378cb93a386Sopenharmony_ci#endif
379cb93a386Sopenharmony_ci        if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType ||
380cb93a386Sopenharmony_ci            ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
381cb93a386Sopenharmony_ci            // On Angle D3D we will hit a limit of out variables if we use too many stages.
382cb93a386Sopenharmony_ci            maxTreeLevels = 2;
383cb93a386Sopenharmony_ci        }
384cb93a386Sopenharmony_ci    }
385cb93a386Sopenharmony_ci    return maxTreeLevels;
386cb93a386Sopenharmony_ci}
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_cistatic void test_programs(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& ctxInfo) {
389cb93a386Sopenharmony_ci    int maxStages = get_programs_max_stages(ctxInfo);
390cb93a386Sopenharmony_ci    if (maxStages == 0) {
391cb93a386Sopenharmony_ci        return;
392cb93a386Sopenharmony_ci    }
393cb93a386Sopenharmony_ci    int maxLevels = get_programs_max_levels(ctxInfo);
394cb93a386Sopenharmony_ci    if (maxLevels == 0) {
395cb93a386Sopenharmony_ci        return;
396cb93a386Sopenharmony_ci    }
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.directContext(), maxStages,
399cb93a386Sopenharmony_ci                                                                maxLevels));
400cb93a386Sopenharmony_ci}
401cb93a386Sopenharmony_ci
402cb93a386Sopenharmony_ciDEF_GPUTEST(Programs, reporter, options) {
403cb93a386Sopenharmony_ci    // Set a locale that would cause shader compilation to fail because of , as decimal separator.
404cb93a386Sopenharmony_ci    // skbug 3330
405cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_WIN
406cb93a386Sopenharmony_ci    GrAutoLocaleSetter als("sv-SE");
407cb93a386Sopenharmony_ci#else
408cb93a386Sopenharmony_ci    GrAutoLocaleSetter als("sv_SE.UTF-8");
409cb93a386Sopenharmony_ci#endif
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci    // We suppress prints to avoid spew
412cb93a386Sopenharmony_ci    GrContextOptions opts = options;
413cb93a386Sopenharmony_ci    opts.fSuppressPrints = true;
414cb93a386Sopenharmony_ci    sk_gpu_test::GrContextFactory debugFactory(opts);
415cb93a386Sopenharmony_ci    skiatest::RunWithGPUTestContexts(
416cb93a386Sopenharmony_ci            test_programs, &sk_gpu_test::GrContextFactory::IsRenderingContext, reporter, opts);
417cb93a386Sopenharmony_ci}
418