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 SkString temp = this->invokeChild(0, args);
119 args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, temp.c_str());
120 }
121
122 private:
123 typedef GrGLSLFragmentProcessor INHERITED;
124 };
125
BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child)126 BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child)
127 : INHERITED(kBlockInputFragmentProcessor_ClassID, kNone_OptimizationFlags) {
128 this->registerChildProcessor(std::move(child));
129 }
130
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const131 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {}
132
onIsEqual(const GrFragmentProcessor &) const133 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
134
135 typedef GrFragmentProcessor INHERITED;
136 };
137
138 //////////////////////////////////////////////////////////////////////////////
139
140 /*
141 * Begin test code
142 */
143 static const int kRenderTargetHeight = 1;
144 static const int kRenderTargetWidth = 1;
145
random_render_target_context(GrContext * context,SkRandom * random,const GrCaps * caps)146 static std::unique_ptr<GrRenderTargetContext> random_render_target_context(GrContext* context,
147 SkRandom* random,
148 const GrCaps* caps) {
149 GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin
150 : kBottomLeft_GrSurfaceOrigin;
151
152 GrColorType ct = GrColorType::kRGBA_8888;
153 const GrBackendFormat format = caps->getDefaultBackendFormat(ct, GrRenderable::kYes);
154
155 int sampleCnt = random->nextBool() ? caps->getRenderTargetSampleCount(2, format) : 1;
156 // Above could be 0 if msaa isn't supported.
157 sampleCnt = std::max(1, sampleCnt);
158
159 return GrRenderTargetContext::Make(
160 context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
161 {kRenderTargetWidth, kRenderTargetHeight}, sampleCnt, GrMipMapped::kNo,
162 GrProtected::kNo, origin);
163 }
164
165 #if GR_TEST_UTILS
set_random_xpf(GrPaint * paint,GrProcessorTestData * d)166 static void set_random_xpf(GrPaint* paint, GrProcessorTestData* d) {
167 paint->setXPFactory(GrXPFactoryTestFactory::Get(d));
168 }
169
create_random_proc_tree(GrProcessorTestData * d,int minLevels,int maxLevels)170 static std::unique_ptr<GrFragmentProcessor> create_random_proc_tree(GrProcessorTestData* d,
171 int minLevels, int maxLevels) {
172 SkASSERT(1 <= minLevels);
173 SkASSERT(minLevels <= maxLevels);
174
175 // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate.
176 // If returning a leaf node, make sure that it doesn't have children (e.g. another
177 // GrComposeEffect)
178 const float terminateProbability = 0.3f;
179 if (1 == minLevels) {
180 bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability);
181 if (terminate) {
182 std::unique_ptr<GrFragmentProcessor> fp;
183 while (true) {
184 fp = GrFragmentProcessorTestFactory::Make(d);
185 if (!fp) {
186 return nullptr;
187 }
188 if (0 == fp->numChildProcessors()) {
189 break;
190 }
191 }
192 return fp;
193 }
194 }
195 // If we didn't terminate, choose either the left or right subtree to fulfill
196 // the minLevels requirement of this tree; the other child can have as few levels as it wants.
197 // Also choose a random xfer mode.
198 if (minLevels > 1) {
199 --minLevels;
200 }
201 auto minLevelsChild = create_random_proc_tree(d, minLevels, maxLevels - 1);
202 std::unique_ptr<GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, maxLevels - 1));
203 if (!minLevelsChild || !otherChild) {
204 return nullptr;
205 }
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
set_random_color_coverage_stages(GrPaint * paint,GrProcessorTestData * d,int maxStages,int maxTreeLevels)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; ++s) {
237 std::unique_ptr<GrFragmentProcessor> fp(GrFragmentProcessorTestFactory::Make(d));
238 if (!fp) {
239 continue;
240 }
241 // finally add the stage to the correct pipeline in the drawstate
242 if (s < numColorProcs) {
243 paint->addColorFragmentProcessor(std::move(fp));
244 } else {
245 paint->addCoverageFragmentProcessor(std::move(fp));
246 }
247 }
248 }
249 }
250
251 #endif
252
253 #if !GR_TEST_UTILS
ProgramUnitTest(GrContext *,int)254 bool GrDrawingManager::ProgramUnitTest(GrContext*, int) { return true; }
255 #else
ProgramUnitTest(GrContext * context,int maxStages,int maxLevels)256 bool GrDrawingManager::ProgramUnitTest(GrContext* context, int maxStages, int maxLevels) {
257 GrDrawingManager* drawingManager = context->priv().drawingManager();
258 GrProxyProvider* proxyProvider = context->priv().proxyProvider();
259
260 GrProcessorTestData::ViewInfo views[2];
261
262 // setup dummy textures
263 GrMipMapped mipMapped = GrMipMapped(context->priv().caps()->mipMapSupport());
264 {
265 static constexpr SkISize kDummyDims = {34, 18};
266 const GrBackendFormat format =
267 context->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
268 GrRenderable::kYes);
269 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, GrColorType::kRGBA_8888);
270 auto proxy = proxyProvider->createProxy(format, kDummyDims, swizzle, GrRenderable::kYes, 1,
271 mipMapped, SkBackingFit::kExact, SkBudgeted::kNo,
272 GrProtected::kNo, GrInternalSurfaceFlags::kNone);
273 views[0] = {{std::move(proxy), kBottomLeft_GrSurfaceOrigin, swizzle},
274 GrColorType::kRGBA_8888, kPremul_SkAlphaType};
275 }
276 {
277 static constexpr SkISize kDummyDims = {16, 22};
278 const GrBackendFormat format =
279 context->priv().caps()->getDefaultBackendFormat(GrColorType::kAlpha_8,
280 GrRenderable::kNo);
281 GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, GrColorType::kAlpha_8);
282 auto proxy = proxyProvider->createProxy(format, kDummyDims, swizzle, GrRenderable::kNo, 1,
283 mipMapped, SkBackingFit::kExact, SkBudgeted::kNo,
284 GrProtected::kNo, GrInternalSurfaceFlags::kNone);
285 views[1] = {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle},
286 GrColorType::kAlpha_8, kPremul_SkAlphaType};
287 }
288
289 if (!std::get<0>(views[0]) || !std::get<0>(views[1])) {
290 SkDebugf("Could not allocate dummy textures");
291 return false;
292 }
293
294 SkRandom random;
295 static const int NUM_TESTS = 1024;
296 for (int t = 0; t < NUM_TESTS; t++) {
297 // setup random render target(can fail)
298 auto renderTargetContext =
299 random_render_target_context(context, &random, context->priv().caps());
300 if (!renderTargetContext) {
301 SkDebugf("Could not allocate renderTargetContext");
302 return false;
303 }
304
305 GrPaint paint;
306 GrProcessorTestData ptd(&random, context, 2, views);
307 set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels);
308 set_random_xpf(&paint, &ptd);
309 GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
310 }
311 // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
312 drawingManager->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(),
313 GrPrepareForExternalIORequests());
314
315 // Validate that GrFPs work correctly without an input.
316 auto renderTargetContext = GrRenderTargetContext::Make(
317 context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
318 {kRenderTargetWidth, kRenderTargetHeight});
319 if (!renderTargetContext) {
320 SkDebugf("Could not allocate a renderTargetContext");
321 return false;
322 }
323
324 int fpFactoryCnt = GrFragmentProcessorTestFactory::Count();
325 for (int i = 0; i < fpFactoryCnt; ++i) {
326 // Since FP factories internally randomize, call each 10 times.
327 for (int j = 0; j < 10; ++j) {
328 GrProcessorTestData ptd(&random, context, 2, views);
329
330 GrPaint paint;
331 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
332 auto fp = GrFragmentProcessorTestFactory::MakeIdx(i, &ptd);
333 auto blockFP = BlockInputFragmentProcessor::Make(std::move(fp));
334 paint.addColorFragmentProcessor(std::move(blockFP));
335 GrDrawRandomOp(&random, renderTargetContext.get(), std::move(paint));
336 drawingManager->flush(nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess,
337 GrFlushInfo(), GrPrepareForExternalIORequests());
338 }
339 }
340
341 return true;
342 }
343 #endif
344
get_programs_max_stages(const sk_gpu_test::ContextInfo & ctxInfo)345 static int get_programs_max_stages(const sk_gpu_test::ContextInfo& ctxInfo) {
346 GrContext* context = ctxInfo.grContext();
347 int maxStages = 6;
348 if (skiatest::IsGLContextType(ctxInfo.type())) {
349 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->priv().getGpu());
350 if (kGLES_GrGLStandard == gpu->glStandard()) {
351 // We've had issues with driver crashes and HW limits being exceeded with many effects on
352 // Android devices. We have passes on ARM devices with the default number of stages.
353 // TODO When we run ES 3.00 GLSL in more places, test again
354 #ifdef SK_BUILD_FOR_ANDROID
355 if (kARM_GrGLVendor != gpu->ctxInfo().vendor()) {
356 maxStages = 1;
357 }
358 #endif
359 // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
360 #ifdef SK_BUILD_FOR_IOS
361 maxStages = 3;
362 #endif
363 }
364 if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType ||
365 ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
366 // On Angle D3D we will hit a limit of out variables if we use too many stages.
367 maxStages = 3;
368 }
369 }
370 return maxStages;
371 }
372
get_programs_max_levels(const sk_gpu_test::ContextInfo & ctxInfo)373 static int get_programs_max_levels(const sk_gpu_test::ContextInfo& ctxInfo) {
374 // A full tree with 5 levels (31 nodes) may cause a program that exceeds shader limits
375 // (e.g. uniform or varying limits); maxTreeLevels should be a number from 1 to 4 inclusive.
376 int maxTreeLevels = 4;
377 if (skiatest::IsGLContextType(ctxInfo.type())) {
378 // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
379 #ifdef SK_BUILD_FOR_IOS
380 maxTreeLevels = 2;
381 #endif
382 #ifdef SK_BUILD_FOR_ANDROID
383 GrGLGpu* gpu = static_cast<GrGLGpu*>(ctxInfo.grContext()->priv().getGpu());
384 // Tecno Spark 3 Pro with Power VR Rogue GE8300 will fail shader compiles with
385 // no message if the shader is particularly long.
386 if (gpu->ctxInfo().vendor() == kImagination_GrGLVendor) {
387 maxTreeLevels = 3;
388 }
389 #endif
390 if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType ||
391 ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
392 // On Angle D3D we will hit a limit of out variables if we use too many stages.
393 maxTreeLevels = 2;
394 }
395 }
396 return maxTreeLevels;
397 }
398
test_programs(skiatest::Reporter * reporter,const sk_gpu_test::ContextInfo & ctxInfo)399 static void test_programs(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& ctxInfo) {
400 int maxStages = get_programs_max_stages(ctxInfo);
401 if (maxStages == 0) {
402 return;
403 }
404 int maxLevels = get_programs_max_levels(ctxInfo);
405 if (maxLevels == 0) {
406 return;
407 }
408
409 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.grContext(), maxStages,
410 maxLevels));
411 }
412
DEF_GPUTEST(Programs,reporter,options)413 DEF_GPUTEST(Programs, reporter, options) {
414 // Set a locale that would cause shader compilation to fail because of , as decimal separator.
415 // skbug 3330
416 #ifdef SK_BUILD_FOR_WIN
417 GrAutoLocaleSetter als("sv-SE");
418 #else
419 GrAutoLocaleSetter als("sv_SE.UTF-8");
420 #endif
421
422 // We suppress prints to avoid spew
423 GrContextOptions opts = options;
424 opts.fSuppressPrints = true;
425 sk_gpu_test::GrContextFactory debugFactory(opts);
426 skiatest::RunWithGPUTestContexts(test_programs, &skiatest::IsRenderingGLOrMetalContextType,
427 reporter, opts);
428 }
429