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