1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 // This is a GPU-backend specific test. It relies on static intializers to work 10 11 #include "SkTypes.h" 12 13 #if SK_SUPPORT_GPU && SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 14 15 #include "GrAutoLocaleSetter.h" 16 #include "GrBatchTest.h" 17 #include "GrContextFactory.h" 18 #include "GrDrawContext.h" 19 #include "GrDrawingManager.h" 20 #include "GrInvariantOutput.h" 21 #include "GrPipeline.h" 22 #include "GrResourceProvider.h" 23 #include "GrTest.h" 24 #include "GrXferProcessor.h" 25 #include "SkChecksum.h" 26 #include "SkRandom.h" 27 #include "Test.h" 28 29 #include "batches/GrDrawBatch.h" 30 31 #include "effects/GrConfigConversionEffect.h" 32 #include "effects/GrPorterDuffXferProcessor.h" 33 #include "effects/GrXfermodeFragmentProcessor.h" 34 35 #include "gl/GrGLGpu.h" 36 #include "glsl/GrGLSLFragmentProcessor.h" 37 #include "glsl/GrGLSLFragmentShaderBuilder.h" 38 #include "glsl/GrGLSLProgramBuilder.h" 39 40 /* 41 * A dummy processor which just tries to insert a massive key and verify that it can retrieve the 42 * whole thing correctly 43 */ 44 static const uint32_t kMaxKeySize = 1024; 45 46 class GLBigKeyProcessor : public GrGLSLFragmentProcessor { 47 public: 48 void emitCode(EmitArgs& args) override { 49 // pass through 50 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 51 if (args.fInputColor) { 52 fragBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor); 53 } else { 54 fragBuilder->codeAppendf("%s = vec4(1.0);\n", args.fOutputColor); 55 } 56 } 57 58 static void GenKey(const GrProcessor& processor, const GrGLSLCaps&, GrProcessorKeyBuilder* b) { 59 for (uint32_t i = 0; i < kMaxKeySize; i++) { 60 b->add32(i); 61 } 62 } 63 64 private: 65 typedef GrGLSLFragmentProcessor INHERITED; 66 }; 67 68 class BigKeyProcessor : public GrFragmentProcessor { 69 public: 70 static GrFragmentProcessor* Create() { 71 return new BigKeyProcessor; 72 } 73 74 const char* name() const override { return "Big Ole Key"; } 75 76 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 77 return new GLBigKeyProcessor; 78 } 79 80 private: 81 BigKeyProcessor() { 82 this->initClassID<BigKeyProcessor>(); 83 } 84 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps, 85 GrProcessorKeyBuilder* b) const override { 86 GLBigKeyProcessor::GenKey(*this, caps, b); 87 } 88 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 89 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { } 90 91 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 92 93 typedef GrFragmentProcessor INHERITED; 94 }; 95 96 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor); 97 98 const GrFragmentProcessor* BigKeyProcessor::TestCreate(GrProcessorTestData*) { 99 return BigKeyProcessor::Create(); 100 } 101 102 ////////////////////////////////////////////////////////////////////////////// 103 104 class BlockInputFragmentProcessor : public GrFragmentProcessor { 105 public: 106 static GrFragmentProcessor* Create(const GrFragmentProcessor* fp) { 107 return new BlockInputFragmentProcessor(fp); 108 } 109 110 const char* name() const override { return "Block Input"; } 111 112 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; } 113 114 private: 115 class GLFP : public GrGLSLFragmentProcessor { 116 public: 117 void emitCode(EmitArgs& args) override { 118 this->emitChild(0, nullptr, args); 119 } 120 121 private: 122 typedef GrGLSLFragmentProcessor INHERITED; 123 }; 124 125 BlockInputFragmentProcessor(const GrFragmentProcessor* child) { 126 this->initClassID<BlockInputFragmentProcessor>(); 127 this->registerChildProcessor(child); 128 } 129 130 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {} 131 132 bool onIsEqual(const GrFragmentProcessor&) const override { return true; } 133 134 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { 135 inout->setToOther(kRGBA_GrColorComponentFlags, GrColor_WHITE, 136 GrInvariantOutput::kWillNot_ReadInput); 137 this->childProcessor(0).computeInvariantOutput(inout); 138 } 139 140 typedef GrFragmentProcessor INHERITED; 141 }; 142 143 ////////////////////////////////////////////////////////////////////////////// 144 145 /* 146 * Begin test code 147 */ 148 static const int kRenderTargetHeight = 1; 149 static const int kRenderTargetWidth = 1; 150 151 static GrRenderTarget* random_render_target(GrTextureProvider* textureProvider, SkRandom* random, 152 const GrCaps* caps) { 153 // setup render target 154 GrTextureParams params; 155 GrSurfaceDesc texDesc; 156 texDesc.fWidth = kRenderTargetWidth; 157 texDesc.fHeight = kRenderTargetHeight; 158 texDesc.fFlags = kRenderTarget_GrSurfaceFlag; 159 texDesc.fConfig = kRGBA_8888_GrPixelConfig; 160 texDesc.fOrigin = random->nextBool() == true ? kTopLeft_GrSurfaceOrigin : 161 kBottomLeft_GrSurfaceOrigin; 162 texDesc.fSampleCnt = random->nextBool() == true ? SkTMin(4, caps->maxSampleCount()) : 0; 163 164 GrUniqueKey key; 165 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); 166 GrUniqueKey::Builder builder(&key, kDomain, 2); 167 builder[0] = texDesc.fOrigin; 168 builder[1] = texDesc.fSampleCnt; 169 builder.finish(); 170 171 GrTexture* texture = textureProvider->findAndRefTextureByUniqueKey(key); 172 if (!texture) { 173 texture = textureProvider->createTexture(texDesc, SkBudgeted::kYes); 174 if (texture) { 175 textureProvider->assignUniqueKeyToTexture(key, texture); 176 } 177 } 178 return texture ? texture->asRenderTarget() : nullptr; 179 } 180 181 static void set_random_xpf(GrPipelineBuilder* pipelineBuilder, GrProcessorTestData* d) { 182 SkAutoTUnref<const GrXPFactory> xpf(GrProcessorTestFactory<GrXPFactory>::Create(d)); 183 SkASSERT(xpf); 184 pipelineBuilder->setXPFactory(xpf.get()); 185 } 186 187 static const GrFragmentProcessor* create_random_proc_tree(GrProcessorTestData* d, 188 int minLevels, int maxLevels) { 189 SkASSERT(1 <= minLevels); 190 SkASSERT(minLevels <= maxLevels); 191 192 // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate. 193 // If returning a leaf node, make sure that it doesn't have children (e.g. another 194 // GrComposeEffect) 195 const float terminateProbability = 0.3f; 196 if (1 == minLevels) { 197 bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability); 198 if (terminate) { 199 const GrFragmentProcessor* fp; 200 while (true) { 201 fp = GrProcessorTestFactory<GrFragmentProcessor>::Create(d); 202 SkASSERT(fp); 203 if (0 == fp->numChildProcessors()) { 204 break; 205 } 206 fp->unref(); 207 } 208 return fp; 209 } 210 } 211 // If we didn't terminate, choose either the left or right subtree to fulfill 212 // the minLevels requirement of this tree; the other child can have as few levels as it wants. 213 // Also choose a random xfer mode that's supported by CreateFrom2Procs(). 214 if (minLevels > 1) { 215 --minLevels; 216 } 217 SkAutoTUnref<const GrFragmentProcessor> minLevelsChild(create_random_proc_tree(d, minLevels, 218 maxLevels - 1)); 219 SkAutoTUnref<const GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, 220 maxLevels - 1)); 221 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(d->fRandom->nextRangeU(0, 222 SkXfermode::kLastCoeffMode)); 223 const GrFragmentProcessor* fp; 224 if (d->fRandom->nextF() < 0.5f) { 225 fp = GrXfermodeFragmentProcessor::CreateFromTwoProcessors(minLevelsChild, otherChild, mode); 226 SkASSERT(fp); 227 } else { 228 fp = GrXfermodeFragmentProcessor::CreateFromTwoProcessors(otherChild, minLevelsChild, mode); 229 SkASSERT(fp); 230 } 231 return fp; 232 } 233 234 static void set_random_color_coverage_stages(GrPipelineBuilder* pipelineBuilder, 235 GrProcessorTestData* d, int maxStages) { 236 // Randomly choose to either create a linear pipeline of procs or create one proc tree 237 const float procTreeProbability = 0.5f; 238 if (d->fRandom->nextF() < procTreeProbability) { 239 // A full tree with 5 levels (31 nodes) may exceed the max allowed length of the gl 240 // processor key; maxTreeLevels should be a number from 1 to 4 inclusive. 241 const int maxTreeLevels = 4; 242 SkAutoTUnref<const GrFragmentProcessor> fp( 243 create_random_proc_tree(d, 2, maxTreeLevels)); 244 pipelineBuilder->addColorFragmentProcessor(fp); 245 } else { 246 int numProcs = d->fRandom->nextULessThan(maxStages + 1); 247 int numColorProcs = d->fRandom->nextULessThan(numProcs + 1); 248 249 for (int s = 0; s < numProcs;) { 250 SkAutoTUnref<const GrFragmentProcessor> fp( 251 GrProcessorTestFactory<GrFragmentProcessor>::Create(d)); 252 SkASSERT(fp); 253 254 // finally add the stage to the correct pipeline in the drawstate 255 if (s < numColorProcs) { 256 pipelineBuilder->addColorFragmentProcessor(fp); 257 } else { 258 pipelineBuilder->addCoverageFragmentProcessor(fp); 259 } 260 ++s; 261 } 262 } 263 } 264 265 static void set_random_state(GrPipelineBuilder* pipelineBuilder, SkRandom* random) { 266 int state = 0; 267 for (int i = 1; i <= GrPipelineBuilder::kLast_Flag; i <<= 1) { 268 state |= random->nextBool() * i; 269 } 270 271 // If we don't have an MSAA rendertarget then we have to disable useHWAA 272 if ((state | GrPipelineBuilder::kHWAntialias_Flag) && 273 !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled()) { 274 state &= ~GrPipelineBuilder::kHWAntialias_Flag; 275 } 276 pipelineBuilder->enableState(state); 277 } 278 279 // right now, the only thing we seem to care about in drawState's stencil is 'doesWrite()' 280 static void set_random_stencil(GrPipelineBuilder* pipelineBuilder, SkRandom* random) { 281 GR_STATIC_CONST_SAME_STENCIL(kDoesWriteStencil, 282 kReplace_StencilOp, 283 kReplace_StencilOp, 284 kAlways_StencilFunc, 285 0xffff, 286 0xffff, 287 0xffff); 288 GR_STATIC_CONST_SAME_STENCIL(kDoesNotWriteStencil, 289 kKeep_StencilOp, 290 kKeep_StencilOp, 291 kNever_StencilFunc, 292 0xffff, 293 0xffff, 294 0xffff); 295 296 if (random->nextBool()) { 297 pipelineBuilder->setStencil(kDoesWriteStencil); 298 } else { 299 pipelineBuilder->setStencil(kDoesNotWriteStencil); 300 } 301 } 302 303 bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages) { 304 GrDrawingManager* drawingManager = context->drawingManager(); 305 306 // setup dummy textures 307 GrSurfaceDesc dummyDesc; 308 dummyDesc.fFlags = kRenderTarget_GrSurfaceFlag; 309 dummyDesc.fConfig = kSkia8888_GrPixelConfig; 310 dummyDesc.fWidth = 34; 311 dummyDesc.fHeight = 18; 312 SkAutoTUnref<GrTexture> dummyTexture1( 313 context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0)); 314 dummyDesc.fFlags = kNone_GrSurfaceFlags; 315 dummyDesc.fConfig = kAlpha_8_GrPixelConfig; 316 dummyDesc.fWidth = 16; 317 dummyDesc.fHeight = 22; 318 SkAutoTUnref<GrTexture> dummyTexture2( 319 context->textureProvider()->createTexture(dummyDesc, SkBudgeted::kNo, nullptr, 0)); 320 321 if (!dummyTexture1 || ! dummyTexture2) { 322 SkDebugf("Could not allocate dummy textures"); 323 return false; 324 } 325 326 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; 327 328 // dummy scissor state 329 GrScissorState scissor; 330 331 // wide open clip 332 GrClip clip; 333 334 SkRandom random; 335 static const int NUM_TESTS = 2048; 336 for (int t = 0; t < NUM_TESTS; t++) { 337 // setup random render target(can fail) 338 SkAutoTUnref<GrRenderTarget> rt(random_render_target( 339 context->textureProvider(), &random, context->caps())); 340 if (!rt.get()) { 341 SkDebugf("Could not allocate render target"); 342 return false; 343 } 344 345 GrPipelineBuilder pipelineBuilder; 346 pipelineBuilder.setRenderTarget(rt.get()); 347 pipelineBuilder.setClip(clip); 348 349 SkAutoTUnref<GrDrawBatch> batch(GrRandomDrawBatch(&random, context)); 350 SkASSERT(batch); 351 352 GrProcessorTestData ptd(&random, context, context->caps(), rt, dummyTextures); 353 set_random_color_coverage_stages(&pipelineBuilder, &ptd, maxStages); 354 set_random_xpf(&pipelineBuilder, &ptd); 355 set_random_state(&pipelineBuilder, &random); 356 set_random_stencil(&pipelineBuilder, &random); 357 358 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt)); 359 if (!drawContext) { 360 SkDebugf("Could not allocate drawContext"); 361 return false; 362 } 363 364 drawContext->internal_drawBatch(pipelineBuilder, batch); 365 } 366 // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes) 367 drawingManager->flush(); 368 369 // Validate that GrFPs work correctly without an input. 370 GrSurfaceDesc rtDesc; 371 rtDesc.fWidth = kRenderTargetWidth; 372 rtDesc.fHeight = kRenderTargetHeight; 373 rtDesc.fFlags = kRenderTarget_GrSurfaceFlag; 374 rtDesc.fConfig = kRGBA_8888_GrPixelConfig; 375 SkAutoTUnref<GrRenderTarget> rt( 376 context->textureProvider()->createTexture(rtDesc, SkBudgeted::kNo)->asRenderTarget()); 377 int fpFactoryCnt = GrProcessorTestFactory<GrFragmentProcessor>::Count(); 378 for (int i = 0; i < fpFactoryCnt; ++i) { 379 // Since FP factories internally randomize, call each 10 times. 380 for (int j = 0; j < 10; ++j) { 381 SkAutoTUnref<GrDrawBatch> batch(GrRandomDrawBatch(&random, context)); 382 SkASSERT(batch); 383 GrProcessorTestData ptd(&random, context, context->caps(), rt, dummyTextures); 384 GrPipelineBuilder builder; 385 builder.setXPFactory(GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref(); 386 builder.setRenderTarget(rt); 387 builder.setClip(clip); 388 389 SkAutoTUnref<const GrFragmentProcessor> fp( 390 GrProcessorTestFactory<GrFragmentProcessor>::CreateIdx(i, &ptd)); 391 SkAutoTUnref<const GrFragmentProcessor> blockFP( 392 BlockInputFragmentProcessor::Create(fp)); 393 builder.addColorFragmentProcessor(blockFP); 394 395 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt)); 396 if (!drawContext) { 397 SkDebugf("Could not allocate a drawcontext"); 398 return false; 399 } 400 401 drawContext->internal_drawBatch(builder, batch); 402 drawingManager->flush(); 403 } 404 } 405 406 return true; 407 } 408 409 static int get_glprograms_max_stages(GrContext* context) { 410 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu()); 411 /* 412 * For the time being, we only support the test with desktop GL or for android on 413 * ARM platforms 414 * TODO When we run ES 3.00 GLSL in more places, test again 415 */ 416 if (kGL_GrGLStandard == gpu->glStandard() || 417 kARM_GrGLVendor == gpu->ctxInfo().vendor()) { 418 return 6; 419 } else if (kTegra3_GrGLRenderer == gpu->ctxInfo().renderer() || 420 kOther_GrGLRenderer == gpu->ctxInfo().renderer()) { 421 return 1; 422 } 423 return 0; 424 } 425 426 static void test_glprograms_native(skiatest::Reporter* reporter, GrContext* context) { 427 int maxStages = get_glprograms_max_stages(context); 428 if (maxStages == 0) { 429 return; 430 } 431 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(context, maxStages)); 432 } 433 434 static void test_glprograms_other_contexts(skiatest::Reporter* reporter, GrContext* context) { 435 int maxStages = get_glprograms_max_stages(context); 436 #ifdef SK_BUILD_FOR_WIN 437 // Some long shaders run out of temporary registers in the D3D compiler on ANGLE and 438 // command buffer. 439 maxStages = SkTMin(maxStages, 2); 440 #endif 441 if (maxStages == 0) { 442 return; 443 } 444 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(context, maxStages)); 445 } 446 447 DEF_GPUTEST(GLPrograms, reporter, /*factory*/) { 448 // Set a locale that would cause shader compilation to fail because of , as decimal separator. 449 // skbug 3330 450 #ifdef SK_BUILD_FOR_WIN 451 GrAutoLocaleSetter als("sv-SE"); 452 #else 453 GrAutoLocaleSetter als("sv_SE.UTF-8"); 454 #endif 455 456 // We suppress prints to avoid spew 457 GrContextOptions opts; 458 opts.fSuppressPrints = true; 459 GrContextFactory debugFactory(opts); 460 skiatest::RunWithGPUTestContexts(test_glprograms_native, skiatest::kNative_GPUTestContexts, 461 reporter, &debugFactory); 462 skiatest::RunWithGPUTestContexts(test_glprograms_other_contexts, 463 skiatest::kOther_GPUTestContexts, reporter, &debugFactory); 464 } 465 466 #endif 467