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