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