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/SkAlphaType.h"
11 #include "include/core/SkBlendMode.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkSize.h"
14 #include "include/core/SkString.h"
15 #include "include/core/SkSurfaceProps.h"
16 #include "include/core/SkTypes.h"
17 #include "include/gpu/GpuTypes.h"
18 #include "include/gpu/GrBackendSurface.h"
19 #include "include/gpu/GrContextOptions.h"
20 #include "include/gpu/GrDirectContext.h"
21 #include "include/gpu/GrTypes.h"
22 #include "include/gpu/gl/GrGLTypes.h"
23 #include "include/private/base/SkDebug.h"
24 #include "include/private/gpu/ganesh/GrTypesPriv.h"
25 #include "src/base/SkRandom.h"
26 #include "src/gpu/KeyBuilder.h"
27 #include "src/gpu/SkBackingFit.h"
28 #include "src/gpu/Swizzle.h"
29 #include "src/gpu/ganesh/GrAutoLocaleSetter.h"
30 #include "src/gpu/ganesh/GrCaps.h"
31 #include "src/gpu/ganesh/GrDirectContextPriv.h"
32 #include "src/gpu/ganesh/GrDrawOpTest.h"
33 #include "src/gpu/ganesh/GrDrawingManager.h"
34 #include "src/gpu/ganesh/GrFragmentProcessor.h"
35 #include "src/gpu/ganesh/GrPaint.h"
36 #include "src/gpu/ganesh/GrProcessorUnitTest.h"
37 #include "src/gpu/ganesh/GrProxyProvider.h"
38 #include "src/gpu/ganesh/GrSurfaceProxy.h"
39 #include "src/gpu/ganesh/SurfaceDrawContext.h"
40 #include "src/gpu/ganesh/effects/GrBlendFragmentProcessor.h"
41 #include "src/gpu/ganesh/effects/GrPorterDuffXferProcessor.h"
42 #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
43 #include "tests/CtsEnforcement.h"
44 #include "tests/Test.h"
45
46 #include <algorithm>
47 #include <array>
48 #include <cstdint>
49 #include <memory>
50 #include <tuple>
51 #include <utility>
52
53 class GrRecordingContext;
54 struct GrShaderCaps;
55
56 #ifdef SK_GL
57 #include "src/gpu/ganesh/gl/GrGLGpu.h"
58 #endif
59
60 /*
61 * A simple processor which just tries to insert a massive key and verify that it can retrieve the
62 * whole thing correctly
63 */
64 static const uint32_t kMaxKeySize = 1024;
65
66 namespace {
67 class BigKeyProcessor : public GrFragmentProcessor {
68 public:
Make()69 static std::unique_ptr<GrFragmentProcessor> Make() {
70 return std::unique_ptr<GrFragmentProcessor>(new BigKeyProcessor);
71 }
72
name() const73 const char* name() const override { return "Big_Ole_Key"; }
74
onMakeProgramImpl() const75 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
76 class Impl : public ProgramImpl {
77 public:
78 void emitCode(EmitArgs& args) override {
79 args.fFragBuilder->codeAppendf("return half4(1);\n");
80 }
81 };
82
83 return std::make_unique<Impl>();
84 }
85
clone() const86 std::unique_ptr<GrFragmentProcessor> clone() const override { return Make(); }
87
88 private:
BigKeyProcessor()89 BigKeyProcessor() : INHERITED(kBigKeyProcessor_ClassID, kNone_OptimizationFlags) {}
onAddToKey(const GrShaderCaps & caps,skgpu::KeyBuilder * b) const90 void onAddToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const override {
91 for (uint32_t i = 0; i < kMaxKeySize; i++) {
92 b->add32(i);
93 }
94 }
onIsEqual(const GrFragmentProcessor &) const95 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
96
97 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
98
99 using INHERITED = GrFragmentProcessor;
100 };
101 } // anonymous namespace
102
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor)103 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BigKeyProcessor)
104
105 #if GR_TEST_UTILS
106 std::unique_ptr<GrFragmentProcessor> BigKeyProcessor::TestCreate(GrProcessorTestData*) {
107 return BigKeyProcessor::Make();
108 }
109 #endif
110
111 //////////////////////////////////////////////////////////////////////////////
112
113 class BlockInputFragmentProcessor : public GrFragmentProcessor {
114 public:
Make(std::unique_ptr<GrFragmentProcessor> fp)115 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp) {
116 return std::unique_ptr<GrFragmentProcessor>(new BlockInputFragmentProcessor(std::move(fp)));
117 }
118
name() const119 const char* name() const override { return "Block_Input"; }
120
onMakeProgramImpl() const121 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override {
122 return std::make_unique<GLFP>();
123 }
124
clone() const125 std::unique_ptr<GrFragmentProcessor> clone() const override {
126 return Make(this->childProcessor(0)->clone());
127 }
128
129 private:
130 class GLFP : public ProgramImpl {
131 public:
emitCode(EmitArgs & args)132 void emitCode(EmitArgs& args) override {
133 SkString temp = this->invokeChild(0, args);
134 args.fFragBuilder->codeAppendf("return %s;", temp.c_str());
135 }
136
137 private:
138 using INHERITED = ProgramImpl;
139 };
140
BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child)141 BlockInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child)
142 : INHERITED(kBlockInputFragmentProcessor_ClassID, kNone_OptimizationFlags) {
143 this->registerChild(std::move(child));
144 }
145
onAddToKey(const GrShaderCaps &,skgpu::KeyBuilder *) const146 void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override {}
147
onIsEqual(const GrFragmentProcessor &) const148 bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
149
150 using INHERITED = GrFragmentProcessor;
151 };
152
153 //////////////////////////////////////////////////////////////////////////////
154
155 /*
156 * Begin test code
157 */
158 static const int kRenderTargetHeight = 1;
159 static const int kRenderTargetWidth = 1;
160
random_surface_draw_context(GrRecordingContext * rContext,SkRandom * random,const GrCaps * caps)161 static std::unique_ptr<skgpu::v1::SurfaceDrawContext> random_surface_draw_context(
162 GrRecordingContext* rContext,
163 SkRandom* random,
164 const GrCaps* caps) {
165 GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin
166 : kBottomLeft_GrSurfaceOrigin;
167
168 GrColorType ct = GrColorType::kRGBA_8888;
169 const GrBackendFormat format = caps->getDefaultBackendFormat(ct, GrRenderable::kYes);
170
171 int sampleCnt = random->nextBool() ? caps->getRenderTargetSampleCount(2, format) : 1;
172 // Above could be 0 if msaa isn't supported.
173 sampleCnt = std::max(1, sampleCnt);
174
175 return skgpu::v1::SurfaceDrawContext::Make(
176 rContext, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
177 {kRenderTargetWidth, kRenderTargetHeight}, SkSurfaceProps(), /*label=*/{},
178 sampleCnt, GrMipmapped::kNo, GrProtected::kNo, origin);
179 }
180
181 #if GR_TEST_UTILS
set_random_xpf(GrPaint * paint,GrProcessorTestData * d)182 static void set_random_xpf(GrPaint* paint, GrProcessorTestData* d) {
183 paint->setXPFactory(GrXPFactoryTestFactory::Get(d));
184 }
185
create_random_proc_tree(GrProcessorTestData * d,int minLevels,int maxLevels)186 static std::unique_ptr<GrFragmentProcessor> create_random_proc_tree(GrProcessorTestData* d,
187 int minLevels, int maxLevels) {
188 SkASSERT(1 <= minLevels);
189 SkASSERT(minLevels <= maxLevels);
190
191 // Return a leaf node if maxLevels is 1 or if we randomly chose to terminate.
192 // If returning a leaf node, make sure that it doesn't have children (e.g. another
193 // GrComposeEffect)
194 const float terminateProbability = 0.3f;
195 if (1 == minLevels) {
196 bool terminate = (1 == maxLevels) || (d->fRandom->nextF() < terminateProbability);
197 if (terminate) {
198 std::unique_ptr<GrFragmentProcessor> fp;
199 while (true) {
200 fp = GrFragmentProcessorTestFactory::Make(d);
201 if (!fp) {
202 return nullptr;
203 }
204 if (0 == fp->numNonNullChildProcessors()) {
205 break;
206 }
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.
214 if (minLevels > 1) {
215 --minLevels;
216 }
217 auto minLevelsChild = create_random_proc_tree(d, minLevels, maxLevels - 1);
218 std::unique_ptr<GrFragmentProcessor> otherChild(create_random_proc_tree(d, 1, maxLevels - 1));
219 if (!minLevelsChild || !otherChild) {
220 return nullptr;
221 }
222 SkBlendMode mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0,
223 (int)SkBlendMode::kLastMode));
224 std::unique_ptr<GrFragmentProcessor> fp;
225 if (d->fRandom->nextF() < 0.5f) {
226 fp = GrBlendFragmentProcessor::Make(std::move(minLevelsChild), std::move(otherChild), mode);
227 SkASSERT(fp);
228 } else {
229 fp = GrBlendFragmentProcessor::Make(std::move(otherChild), std::move(minLevelsChild), mode);
230 SkASSERT(fp);
231 }
232 return fp;
233 }
234
set_random_color_coverage_stages(GrPaint * paint,GrProcessorTestData * d,int maxStages,int maxTreeLevels)235 static void set_random_color_coverage_stages(GrPaint* paint,
236 GrProcessorTestData* d,
237 int maxStages,
238 int maxTreeLevels) {
239 // Randomly choose to either create a linear pipeline of procs or create one proc tree
240 const float procTreeProbability = 0.5f;
241 if (d->fRandom->nextF() < procTreeProbability) {
242 std::unique_ptr<GrFragmentProcessor> fp(create_random_proc_tree(d, 2, maxTreeLevels));
243 if (fp) {
244 paint->setColorFragmentProcessor(std::move(fp));
245 }
246 } else {
247 if (maxStages >= 1) {
248 if (std::unique_ptr<GrFragmentProcessor> fp = GrFragmentProcessorTestFactory::Make(d)) {
249 paint->setColorFragmentProcessor(std::move(fp));
250 }
251 }
252 if (maxStages >= 2) {
253 if (std::unique_ptr<GrFragmentProcessor> fp = GrFragmentProcessorTestFactory::Make(d)) {
254 paint->setCoverageFragmentProcessor(std::move(fp));
255 }
256 }
257 }
258 }
259
260 #endif
261
262 #if !GR_TEST_UTILS
ProgramUnitTest(GrDirectContext *,int)263 bool GrDrawingManager::ProgramUnitTest(GrDirectContext*, int) { return true; }
264 #else
ProgramUnitTest(GrDirectContext * direct,int maxStages,int maxLevels)265 bool GrDrawingManager::ProgramUnitTest(GrDirectContext* direct, int maxStages, int maxLevels) {
266 GrProxyProvider* proxyProvider = direct->priv().proxyProvider();
267 const GrCaps* caps = direct->priv().caps();
268
269 GrProcessorTestData::ViewInfo views[2];
270
271 // setup arbitrary textures
272 GrMipmapped mipmapped = GrMipmapped(caps->mipmapSupport());
273 {
274 static constexpr SkISize kDims = {34, 18};
275 const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kRGBA_8888,
276 GrRenderable::kYes);
277 auto proxy = proxyProvider->createProxy(format,
278 kDims,
279 GrRenderable::kYes,
280 1,
281 mipmapped,
282 SkBackingFit::kExact,
283 skgpu::Budgeted::kNo,
284 GrProtected::kNo,
285 /*label=*/{},
286 GrInternalSurfaceFlags::kNone);
287 skgpu::Swizzle swizzle = caps->getReadSwizzle(format, GrColorType::kRGBA_8888);
288 views[0] = {{std::move(proxy), kBottomLeft_GrSurfaceOrigin, swizzle},
289 GrColorType::kRGBA_8888, kPremul_SkAlphaType};
290 }
291 {
292 static constexpr SkISize kDims = {16, 22};
293 const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8,
294 GrRenderable::kNo);
295 auto proxy = proxyProvider->createProxy(format,
296 kDims,
297 GrRenderable::kNo,
298 1,
299 mipmapped,
300 SkBackingFit::kExact,
301 skgpu::Budgeted::kNo,
302 GrProtected::kNo,
303 /*label=*/{},
304 GrInternalSurfaceFlags::kNone);
305 skgpu::Swizzle swizzle = caps->getReadSwizzle(format, GrColorType::kAlpha_8);
306 views[1] = {{std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle},
307 GrColorType::kAlpha_8, kPremul_SkAlphaType};
308 }
309
310 if (!std::get<0>(views[0]) || !std::get<0>(views[1])) {
311 SkDebugf("Could not allocate textures for test");
312 return false;
313 }
314
315 SkRandom random;
316 static const int NUM_TESTS = 1024;
317 for (int t = 0; t < NUM_TESTS; t++) {
318 // setup random render target(can fail)
319 auto surfaceDrawContext = random_surface_draw_context(direct, &random, caps);
320 if (!surfaceDrawContext) {
321 SkDebugf("Could not allocate surfaceDrawContext");
322 return false;
323 }
324
325 GrPaint paint;
326 GrProcessorTestData ptd(&random, direct, /*maxTreeDepth=*/1, std::size(views), views);
327 set_random_color_coverage_stages(&paint, &ptd, maxStages, maxLevels);
328 set_random_xpf(&paint, &ptd);
329 GrDrawRandomOp(&random, surfaceDrawContext.get(), std::move(paint));
330 }
331 // Flush everything, test passes if flush is successful(ie, no asserts are hit, no crashes)
332 direct->flush(GrFlushInfo());
333 direct->submit(false);
334
335 // Validate that GrFPs work correctly without an input.
336 auto sdc = skgpu::v1::SurfaceDrawContext::Make(
337 direct, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact,
338 {kRenderTargetWidth, kRenderTargetHeight}, SkSurfaceProps(),
339 /*label=*/{});
340 if (!sdc) {
341 SkDebugf("Could not allocate a surfaceDrawContext");
342 return false;
343 }
344
345 int fpFactoryCnt = GrFragmentProcessorTestFactory::Count();
346 for (int i = 0; i < fpFactoryCnt; ++i) {
347 // Since FP factories internally randomize, call each 10 times.
348 for (int j = 0; j < 10; ++j) {
349 GrProcessorTestData ptd(&random, direct, /*maxTreeDepth=*/1, std::size(views),
350 views);
351
352 GrPaint paint;
353 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
354 auto fp = GrFragmentProcessorTestFactory::MakeIdx(i, &ptd);
355 auto blockFP = BlockInputFragmentProcessor::Make(std::move(fp));
356 paint.setColorFragmentProcessor(std::move(blockFP));
357 GrDrawRandomOp(&random, sdc.get(), std::move(paint));
358
359 direct->flush(GrFlushInfo());
360 direct->submit(false);
361 }
362 }
363
364 return true;
365 }
366 #endif
367
get_programs_max_stages(const sk_gpu_test::ContextInfo & ctxInfo)368 static int get_programs_max_stages(const sk_gpu_test::ContextInfo& ctxInfo) {
369 int maxStages = 6;
370 #ifdef SK_GL
371 auto context = ctxInfo.directContext();
372 if (skiatest::IsGLContextType(ctxInfo.type())) {
373 GrGLGpu* gpu = static_cast<GrGLGpu*>(context->priv().getGpu());
374 if (kGLES_GrGLStandard == gpu->glStandard()) {
375 // We've had issues with driver crashes and HW limits being exceeded with many effects on
376 // Android devices. We have passes on ARM devices with the default number of stages.
377 // TODO When we run ES 3.00 GLSL in more places, test again
378 #ifdef SK_BUILD_FOR_ANDROID
379 if (gpu->ctxInfo().vendor() != GrGLVendor::kARM) {
380 maxStages = 1;
381 }
382 #endif
383 // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
384 #ifdef SK_BUILD_FOR_IOS
385 maxStages = 3;
386 #endif
387 }
388 // On Angle D3D we will hit a limit of out variables if we use too many stages. This is
389 // particularly true on D3D9 with a low limit on varyings and the fact that every varying is
390 // packed as though it has 4 components.
391 if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType) {
392 maxStages = 2;
393 } else if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
394 maxStages = 3;
395 }
396 }
397 #endif
398 return maxStages;
399 }
400
get_programs_max_levels(const sk_gpu_test::ContextInfo & ctxInfo)401 static int get_programs_max_levels(const sk_gpu_test::ContextInfo& ctxInfo) {
402 // A full tree with 5 levels (31 nodes) may cause a program that exceeds shader limits
403 // (e.g. uniform or varying limits); maxTreeLevels should be a number from 1 to 4 inclusive.
404 int maxTreeLevels = 4;
405 if (skiatest::IsGLContextType(ctxInfo.type())) {
406 // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627.
407 #ifdef SK_BUILD_FOR_IOS
408 maxTreeLevels = 2;
409 #endif
410 #if defined(SK_BUILD_FOR_ANDROID) && defined(SK_GL)
411 GrGLGpu* gpu = static_cast<GrGLGpu*>(ctxInfo.directContext()->priv().getGpu());
412 // Tecno Spark 3 Pro with Power VR Rogue GE8300 will fail shader compiles with
413 // no message if the shader is particularly long.
414 if (gpu->ctxInfo().vendor() == GrGLVendor::kImagination) {
415 maxTreeLevels = 3;
416 }
417 #endif
418 if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType ||
419 ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) {
420 // On Angle D3D we will hit a limit of out variables if we use too many stages.
421 maxTreeLevels = 2;
422 }
423 }
424 return maxTreeLevels;
425 }
426
test_programs(skiatest::Reporter * reporter,const sk_gpu_test::ContextInfo & ctxInfo)427 static void test_programs(skiatest::Reporter* reporter, const sk_gpu_test::ContextInfo& ctxInfo) {
428 int maxStages = get_programs_max_stages(ctxInfo);
429 if (maxStages == 0) {
430 return;
431 }
432 int maxLevels = get_programs_max_levels(ctxInfo);
433 if (maxLevels == 0) {
434 return;
435 }
436
437 REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest(ctxInfo.directContext(), maxStages,
438 maxLevels));
439 }
440
DEF_GANESH_TEST(Programs,reporter,options,CtsEnforcement::kNever)441 DEF_GANESH_TEST(Programs, reporter, options, CtsEnforcement::kNever) {
442 // Set a locale that would cause shader compilation to fail because of , as decimal separator.
443 // skbug 3330
444 #ifdef SK_BUILD_FOR_WIN
445 GrAutoLocaleSetter als("sv-SE");
446 #else
447 GrAutoLocaleSetter als("sv_SE.UTF-8");
448 #endif
449
450 // We suppress prints to avoid spew
451 GrContextOptions opts = options;
452 opts.fSuppressPrints = true;
453 sk_gpu_test::GrContextFactory debugFactory(opts);
454 skiatest::RunWithGaneshTestContexts(
455 test_programs, &sk_gpu_test::GrContextFactory::IsRenderingContext, reporter, opts);
456 }
457