1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 // This is a GPU-backend specific test. It relies on static intializers to work 9 10 #include "SkTypes.h" 11 12 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 13 14 #include "GrAutoLocaleSetter.h" 15 #include "GrContextFactory.h" 16 #include "GrContextPriv.h" 17 #include "GrDrawOpTest.h" 18 #include "GrDrawingManager.h" 19 #include "GrPipeline.h" 20 #include "GrRenderTargetContextPriv.h" 21 #include "GrTest.h" 22 #include "GrXferProcessor.h" 23 #include "SkChecksum.h" 24 #include "SkRandom.h" 25 #include "Test.h" 26 27 #include "ops/GrDrawOp.h" 28 29 #include "effects/GrConfigConversionEffect.h" 30 #include "effects/GrPorterDuffXferProcessor.h" 31 #include "effects/GrXfermodeFragmentProcessor.h" 32 33 #include "gl/GrGLGpu.h" 34 #include "glsl/GrGLSLFragmentProcessor.h" 35 #include "glsl/GrGLSLFragmentShaderBuilder.h" 36 #include "glsl/GrGLSLProgramBuilder.h" 37 38 /* 39 * A dummy processor which just tries to insert a massive key and verify that it can retrieve the 40 * whole thing correctly 41 */ 42 static const uint32_t kMaxKeySize = 1024; 43 44 class GLBigKeyProcessor : public GrGLSLFragmentProcessor { 45 public: 46 void emitCode(EmitArgs& args) override { 47 // pass through 48 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 49 if (args.fInputColor) { 50 fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor); 51 } else { 52 fragBuilder->codeAppendf("%s = vec4(1.0);\n", args.fOutputColor); 53 } 54 } 55 56 static void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b) { 57 for (uint32_t i = 0; i < kMaxKeySize; i++) { 58 b->add32(i); 59 } 60 } 61 62 private: 63 typedef GrGLSLFragmentProcessor INHERITED; 64 }; 65 66 class BigKeyProcessor : public GrFragmentProcessor { 67 public: 68 static std::unique_ptr<GrFragmentProcessor> Make() { 69 return std::unique_ptr<GrFragmentProcessor>(new BigKeyProcessor); 70 } 71 72 const char* name() const override { return "Big Ole Key"; } 73 74 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 75 return new GLBigKeyProcessor; 76 } 77 78 std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(); } 79 80 private: 81 BigKeyProcessor() : INHERITED(kBigKeyProcessor_ClassID, kNone_OptimizationFlags) { } 82 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps, 83 GrProcessorKeyBuilder* b) const override { 84 GLBigKeyProcessor::GenKey(*this, caps, b); 85 } 86 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 87 88 GR_DECLARE_FRAGMENT_PROCESSOR_TEST 89 90 typedef GrFragmentProcessor INHERITED; 91 }; 92 93 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor); 94 95 #if GR_TEST_UTILS 96 std::unique_ptr<GrFragmentProcessor> BigKeyProcessor::TestCreate(GrProcessorTestData*) { 97 return BigKeyProcessor::Make(); 98 } 99 #endif 100 101 ////////////////////////////////////////////////////////////////////////////// 102 103 class BlockInputFragmentProcessor : public GrFragmentProcessor { 104 public: 105 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp) { 106 return std::unique_ptr<GrFragmentProcessor>(new BlockInputFragmentProcessor(std::move(fp))); 107 } 108 109 const char* name() const override { return "Block Input"; } 110 111 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; } 112 113 std::unique_ptr<GrFragmentProcessor> clone() const override { 114 return Make(this->childProcessor(0).clone()); 115 } 116 117 private: 118 class GLFP : public GrGLSLFragmentProcessor { 119 public: 120 void emitCode(EmitArgs& args) override { 121 this->emitChild(0, args); 122 } 123 124 private: 125 typedef GrGLSLFragmentProcessor INHERITED; 126 }; 127 128 BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child) 129 : INHERITED(kBlockInputFragmentProcessor_ClassID, kNone_OptimizationFlags) { 130 this->registerChildProcessor(std::move(child)); 131 } 132 133 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {} 134 135 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 136 137 typedef GrFragmentProcessor INHERITED; 138 }; 139 140 ////////////////////////////////////////////////////////////////////////////// 141 142 /* 143 * Begin test code 144 */ 145 static const int kRenderTargetHeight = 1; 146 static const int kRenderTargetWidth = 1; 147 148 static sk_sp<GrRenderTargetContext> random_render_target_context(GrContext* context, 149 SkRandom* random, 150 const GrCaps* caps) { 151 GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin 152 : kBottomLeft_GrSurfaceOrigin; 153 int sampleCnt = 154 random->nextBool() ? caps->getRenderTargetSampleCount(2, kRGBA_8888_GrPixelConfig) : 1; 155 // Above could be 0 if msaa isn't supported. 156 sampleCnt = SkTMax(1, sampleCnt); 157 158 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext( 159 SkBackingFit::kExact, 160 kRenderTargetWidth, 161 kRenderTargetHeight, 162 kRGBA_8888_GrPixelConfig, 163 nullptr, 164 sampleCnt, 165 GrMipMapped::kNo, 166 origin)); 167 return renderTargetContext; 168 } 169 170 #if GR_TEST_UTILS 171 static void set_random_xpf(GrPaint* paint, GrProcessorTestData* d) { 172 paint->setXPFactory(GrXPFactoryTestFactory::Get(d)); 173 } 174 175 static std::unique_ptr<GrFragmentProcessor> create_random_proc_tree(GrProcessorTestData* d, 176 int minLevels, int maxLevels) { 177 SkASSERT(1 <= minLevels); 178 SkASSERT(minLevels <= maxLevels); 179 180 // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate. 181 // If returning a leaf node, make sure that it doesn't have children (e.g. another 182 // GrComposeEffect) 183 const float terminateProbability = 0.3f; 184 if (1 == minLevels) { 185 bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability); 186 if (terminate) { 187 std::unique_ptr<GrFragmentProcessor> fp; 188 while (true) { 189 fp = GrFragmentProcessorTestFactory::Make(d); 190 SkASSERT(fp); 191 if (0 == fp->numChildProcessors()) { 192 break; 193 } 194 } 195 return fp; 196 } 197 } 198 // If we didn't terminate, choose either the left or right subtree to fulfill 199 // the minLevels requirement of this tree; the other child can have as few levels as it wants. 200 // Also choose a random xfer mode. 201 if (minLevels > 1) { 202 --minLevels; 203 } 204 auto minLevelsChild = create_random_proc_tree(d, minLevels, maxLevels - 1); 205 std::unique_ptr<GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, maxLevels - 1)); 206 SkBlendMode mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, 207 (int)SkBlendMode::kLastMode)); 208 std::unique_ptr<GrFragmentProcessor> fp; 209 if (d->fRandom->nextF() < 0.5f) { 210 fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(minLevelsChild), 211 std::move(otherChild), mode); 212 SkASSERT(fp); 213 } else { 214 fp = GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(otherChild), 215 std::move(minLevelsChild), mode); 216 SkASSERT(fp); 217 } 218 return fp; 219 } 220 221 static void set_random_color_coverage_stages(GrPaint* paint, 222 GrProcessorTestData* d, 223 int maxStages, 224 int maxTreeLevels) { 225 // Randomly choose to either create a linear pipeline of procs or create one proc tree 226 const float procTreeProbability = 0.5f; 227 if (d->fRandom->nextF() < procTreeProbability) { 228 std::unique_ptr<GrFragmentProcessor> fp(create_random_proc_tree(d, 2, maxTreeLevels)); 229 if (fp) { 230 paint->addColorFragmentProcessor(std::move(fp)); 231 } 232 } else { 233 int numProcs = d->fRandom->nextULessThan(maxStages + 1); 234 int numColorProcs = d->fRandom->nextULessThan(numProcs + 1); 235 236 for (int s = 0; s < numProcs;) { 237 std::unique_ptr<GrFragmentProcessor> fp(GrFragmentProcessorTestFactory::Make(d)); 238 SkASSERT(fp); 239 240 // finally add the stage to the correct pipeline in the drawstate 241 if (s < numColorProcs) { 242 paint->addColorFragmentProcessor(std::move(fp)); 243 } else { 244 paint->addCoverageFragmentProcessor(std::move(fp)); 245 } 246 ++s; 247 } 248 } 249 } 250 251 static void set_random_state(GrPaint* paint, SkRandom* random) { 252 if (random->nextBool()) { 253 paint->setDisableOutputConversionToSRGB(true); 254 } 255 if (random->nextBool()) { 256 paint->setAllowSRGBInputs(true); 257 } 258 } 259 260 #endif 261 262 #if !GR_TEST_UTILS 263 bool GrDrawingManager::ProgramUnitTest(GrContext*, int) { return true; } 264 #else 265 bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages, int maxLevels) { 266 GrDrawingManager* drawingManager = context->contextPriv().drawingManager(); 267 GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider(); 268 269 sk_sp<GrTextureProxy> proxies[2]; 270 271 // setup dummy textures 272 { 273 GrSurfaceDesc dummyDesc; 274 dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag; 275 dummyDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; 276 dummyDesc.fWidth = 34; 277 dummyDesc.fHeight = 18; 278 dummyDesc.fConfig = kRGBA_8888_GrPixelConfig; 279 proxies[0] = proxyProvider->createProxy(dummyDesc, SkBackingFit::kExact, SkBudgeted::kNo); 280 } 281 { 282 GrSurfaceDesc dummyDesc; 283 dummyDesc.fFlags = kNone_GrSurfaceFlags; 284 dummyDesc.fOrigin = kTopLeft_GrSurfaceOrigin; 285 dummyDesc.fWidth = 16; 286 dummyDesc.fHeight = 22; 287 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; 288 proxies[1] = proxyProvider->createProxy(dummyDesc, SkBackingFit::kExact, SkBudgeted::kNo); 289 } 290 291 if (!proxies[0] || !proxies[1]) { 292 SkDebugf("Could not allocate dummy textures"); 293 return false; 294 } 295 296 // dummy scissor state 297 GrScissorState scissor; 298 299 SkRandom random; 300 static const int NUM_TESTS = 1024; 301 for (int t = 0; t < NUM_TESTS; t++) { 302 // setup random render target(can fail) 303 sk_sp<GrRenderTargetContext> renderTargetContext(random_render_target_context( 304 context, &random, context->caps())); 305 if (!renderTargetContext) { 306 SkDebugf("Could not allocate renderTargetContext"); 307 return false; 308 } 309 310 GrPaint paint; 311 GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies); 312 set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels); 313 set_random_xpf(&paint, &ptd); 314 set_random_state(&paint, &random); 315 GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint)); 316 } 317 // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes) 318 drawingManager->flush(nullptr); 319 320 // Validate that GrFPs work correctly without an input. 321 sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext( 322 SkBackingFit::kExact, 323 kRenderTargetWidth, 324 kRenderTargetHeight, 325 kRGBA_8888_GrPixelConfig, 326 nullptr)); 327 if (!renderTargetContext) { 328 SkDebugf("Could not allocate a renderTargetContext"); 329 return false; 330 } 331 332 int fpFactoryCnt = GrFragmentProcessorTestFactory::Count(); 333 for (int i = 0; i < fpFactoryCnt; ++i) { 334 // Since FP factories internally randomize, call each 10 times. 335 for (int j = 0; j < 10; ++j) { 336 GrProcessorTestData ptd(&random, context, renderTargetContext.get(), proxies); 337 338 GrPaint paint; 339 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc)); 340 auto fp = GrFragmentProcessorTestFactory::MakeIdx(i, &ptd); 341 auto blockFP = BlockInputFragmentProcessor::Make(std::move(fp)); 342 paint.addColorFragmentProcessor(std::move(blockFP)); 343 GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint)); 344 drawingManager->flush(nullptr); 345 } 346 } 347 348 return true; 349 } 350 #endif 351 352 static int get_glprograms_max_stages(const sk_gpu_test::ContextInfo& ctxInfo) { 353 GrContext* context = ctxInfo.grContext(); 354 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->contextPriv().getGpu()); 355 int maxStages = 6; 356 if (kGLES_GrGLStandard == gpu->glStandard()) { 357 // We've had issues with driver crashes and HW limits being exceeded with many effects on 358 // Android devices. We have passes on ARM devices with the default number of stages. 359 // TODO When we run ES 3.00 GLSL in more places, test again 360 #ifdef SK_BUILD_FOR_ANDROID 361 if (kARM_GrGLVendor != gpu->ctxInfo().vendor()) { 362 maxStages = 1; 363 } 364 #endif 365 // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627. 366 #ifdef SK_BUILD_FOR_IOS 367 maxStages = 3; 368 #endif 369 } 370 if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType || 371 ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) { 372 // On Angle D3D we will hit a limit of out variables if we use too many stages. 373 maxStages = 3; 374 } 375 return maxStages; 376 } 377 378 static int get_glprograms_max_levels(const sk_gpu_test::ContextInfo& ctxInfo) { 379 // A full tree with 5 levels (31 nodes) may cause a program that exceeds shader limits 380 // (e.g. uniform or varying limits); maxTreeLevels should be a number from 1 to 4 inclusive. 381 int maxTreeLevels = 4; 382 // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627. 383 #ifdef SK_BUILD_FOR_IOS 384 maxTreeLevels = 2; 385 #endif 386 if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType || 387 ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) { 388 // On Angle D3D we will hit a limit of out variables if we use too many stages. 389 maxTreeLevels = 2; 390 } 391 return maxTreeLevels; 392 } 393 394 static void test_glprograms(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& ctxInfo) { 395 int maxStages = get_glprograms_max_stages(ctxInfo); 396 if (maxStages == 0) { 397 return; 398 } 399 int maxLevels = get_glprograms_max_levels(ctxInfo); 400 if (maxLevels == 0) { 401 return; 402 } 403 404 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.grContext(), maxStages, 405 maxLevels)); 406 } 407 408 DEF_GPUTEST(GLPrograms, reporter, options) { 409 // Set a locale that would cause shader compilation to fail because of , as decimal separator. 410 // skbug 3330 411 #ifdef SK_BUILD_FOR_WIN 412 GrAutoLocaleSetter als("sv-SE"); 413 #else 414 GrAutoLocaleSetter als("sv_SE.UTF-8"); 415 #endif 416 417 // We suppress prints to avoid spew 418 GrContextOptions opts = options; 419 opts.fSuppressPrints = true; 420 sk_gpu_test::GrContextFactory debugFactory(opts); 421 skiatest::RunWithGPUTestContexts(test_glprograms, &skiatest::IsRenderingGLContextType, reporter, 422 opts); 423 } 424 425 #endif 426