ProcessorTest.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /*
  2. * Copyright 2016 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. #include "include/core/SkTypes.h"
  8. #include "tests/Test.h"
  9. #include "include/gpu/GrContext.h"
  10. #include "include/gpu/GrGpuResource.h"
  11. #include "src/gpu/GrClip.h"
  12. #include "src/gpu/GrContextPriv.h"
  13. #include "src/gpu/GrMemoryPool.h"
  14. #include "src/gpu/GrProxyProvider.h"
  15. #include "src/gpu/GrRenderTargetContext.h"
  16. #include "src/gpu/GrRenderTargetContextPriv.h"
  17. #include "src/gpu/GrResourceProvider.h"
  18. #include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
  19. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  20. #include "src/gpu/ops/GrFillRectOp.h"
  21. #include "src/gpu/ops/GrMeshDrawOp.h"
  22. #include "tests/TestUtils.h"
  23. #include <atomic>
  24. #include <random>
  25. namespace {
  26. class TestOp : public GrMeshDrawOp {
  27. public:
  28. DEFINE_OP_CLASS_ID
  29. static std::unique_ptr<GrDrawOp> Make(GrContext* context,
  30. std::unique_ptr<GrFragmentProcessor> fp) {
  31. GrOpMemoryPool* pool = context->priv().opMemoryPool();
  32. return pool->allocate<TestOp>(std::move(fp));
  33. }
  34. const char* name() const override { return "TestOp"; }
  35. void visitProxies(const VisitProxyFunc& func) const override {
  36. fProcessors.visitProxies(func);
  37. }
  38. FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
  39. GrProcessorSet::Analysis finalize(
  40. const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
  41. GrClampType clampType) override {
  42. static constexpr GrProcessorAnalysisColor kUnknownColor;
  43. SkPMColor4f overrideColor;
  44. return fProcessors.finalize(
  45. kUnknownColor, GrProcessorAnalysisCoverage::kNone, clip,
  46. &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType,
  47. &overrideColor);
  48. }
  49. private:
  50. friend class ::GrOpMemoryPool; // for ctor
  51. TestOp(std::unique_ptr<GrFragmentProcessor> fp)
  52. : INHERITED(ClassID()), fProcessors(std::move(fp)) {
  53. this->setBounds(SkRect::MakeWH(100, 100), HasAABloat::kNo, IsZeroArea::kNo);
  54. }
  55. void onPrepareDraws(Target* target) override { return; }
  56. void onExecute(GrOpFlushState*, const SkRect&) override { return; }
  57. GrProcessorSet fProcessors;
  58. typedef GrMeshDrawOp INHERITED;
  59. };
  60. /**
  61. * FP used to test ref counts on owned GrGpuResources. Can also be a parent FP to test counts
  62. * of resources owned by child FPs.
  63. */
  64. class TestFP : public GrFragmentProcessor {
  65. public:
  66. static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child) {
  67. return std::unique_ptr<GrFragmentProcessor>(new TestFP(std::move(child)));
  68. }
  69. static std::unique_ptr<GrFragmentProcessor> Make(const SkTArray<sk_sp<GrTextureProxy>>& proxies,
  70. const SkTArray<sk_sp<GrGpuBuffer>>& buffers) {
  71. return std::unique_ptr<GrFragmentProcessor>(new TestFP(proxies, buffers));
  72. }
  73. const char* name() const override { return "test"; }
  74. void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
  75. static std::atomic<int32_t> nextKey{0};
  76. b->add32(nextKey++);
  77. }
  78. std::unique_ptr<GrFragmentProcessor> clone() const override {
  79. return std::unique_ptr<GrFragmentProcessor>(new TestFP(*this));
  80. }
  81. private:
  82. TestFP(const SkTArray<sk_sp<GrTextureProxy>>& proxies,
  83. const SkTArray<sk_sp<GrGpuBuffer>>& buffers)
  84. : INHERITED(kTestFP_ClassID, kNone_OptimizationFlags), fSamplers(4) {
  85. for (const auto& proxy : proxies) {
  86. fSamplers.emplace_back(proxy);
  87. }
  88. this->setTextureSamplerCnt(fSamplers.count());
  89. }
  90. TestFP(std::unique_ptr<GrFragmentProcessor> child)
  91. : INHERITED(kTestFP_ClassID, kNone_OptimizationFlags), fSamplers(4) {
  92. this->registerChildProcessor(std::move(child));
  93. }
  94. explicit TestFP(const TestFP& that)
  95. : INHERITED(kTestFP_ClassID, that.optimizationFlags()), fSamplers(4) {
  96. for (int i = 0; i < that.fSamplers.count(); ++i) {
  97. fSamplers.emplace_back(that.fSamplers[i]);
  98. }
  99. for (int i = 0; i < that.numChildProcessors(); ++i) {
  100. this->registerChildProcessor(that.childProcessor(i).clone());
  101. }
  102. this->setTextureSamplerCnt(fSamplers.count());
  103. }
  104. virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
  105. class TestGLSLFP : public GrGLSLFragmentProcessor {
  106. public:
  107. TestGLSLFP() {}
  108. void emitCode(EmitArgs& args) override {
  109. GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
  110. fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
  111. }
  112. private:
  113. };
  114. return new TestGLSLFP();
  115. }
  116. bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
  117. const TextureSampler& onTextureSampler(int i) const override { return fSamplers[i]; }
  118. GrTAllocator<TextureSampler> fSamplers;
  119. typedef GrFragmentProcessor INHERITED;
  120. };
  121. }
  122. static void check_refs(skiatest::Reporter* reporter,
  123. GrTextureProxy* proxy,
  124. int32_t expectedProxyRefs,
  125. int32_t expectedBackingRefs) {
  126. int32_t actualProxyRefs = proxy->priv().getProxyRefCnt();
  127. int32_t actualBackingRefs = proxy->testingOnly_getBackingRefCnt();
  128. SkASSERT(actualProxyRefs == expectedProxyRefs);
  129. SkASSERT(actualBackingRefs == expectedBackingRefs);
  130. REPORTER_ASSERT(reporter, actualProxyRefs == expectedProxyRefs);
  131. REPORTER_ASSERT(reporter, actualBackingRefs == expectedBackingRefs);
  132. }
  133. DEF_GPUTEST_FOR_ALL_CONTEXTS(ProcessorRefTest, reporter, ctxInfo) {
  134. GrContext* context = ctxInfo.grContext();
  135. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  136. GrSurfaceDesc desc;
  137. desc.fWidth = 10;
  138. desc.fHeight = 10;
  139. desc.fConfig = kRGBA_8888_GrPixelConfig;
  140. const GrBackendFormat format =
  141. context->priv().caps()->getBackendFormatFromColorType(GrColorType::kRGBA_8888);
  142. for (bool makeClone : {false, true}) {
  143. for (int parentCnt = 0; parentCnt < 2; parentCnt++) {
  144. sk_sp<GrRenderTargetContext> renderTargetContext(
  145. context->priv().makeDeferredRenderTargetContext(
  146. SkBackingFit::kApprox, 1, 1, GrColorType::kRGBA_8888, nullptr));
  147. {
  148. sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(
  149. format, desc, GrRenderable::kNo, 1, kTopLeft_GrSurfaceOrigin,
  150. SkBackingFit::kExact, SkBudgeted::kYes, GrProtected::kNo);
  151. {
  152. SkTArray<sk_sp<GrTextureProxy>> proxies;
  153. SkTArray<sk_sp<GrGpuBuffer>> buffers;
  154. proxies.push_back(proxy);
  155. auto fp = TestFP::Make(std::move(proxies), std::move(buffers));
  156. for (int i = 0; i < parentCnt; ++i) {
  157. fp = TestFP::Make(std::move(fp));
  158. }
  159. std::unique_ptr<GrFragmentProcessor> clone;
  160. if (makeClone) {
  161. clone = fp->clone();
  162. }
  163. std::unique_ptr<GrDrawOp> op(TestOp::Make(context, std::move(fp)));
  164. renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
  165. if (clone) {
  166. op = TestOp::Make(context, std::move(clone));
  167. renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
  168. }
  169. }
  170. // If the fp is cloned the number of refs should increase by one (for the clone)
  171. int expectedProxyRefs = makeClone ? 3 : 2;
  172. check_refs(reporter, proxy.get(), expectedProxyRefs, -1);
  173. context->flush();
  174. check_refs(reporter, proxy.get(), 1, 1); // just one from the 'proxy' sk_sp
  175. }
  176. }
  177. }
  178. }
  179. #include "tools/flags/CommandLineFlags.h"
  180. static DEFINE_bool(randomProcessorTest, false,
  181. "Use non-deterministic seed for random processor tests?");
  182. static DEFINE_int(processorSeed, 0,
  183. "Use specific seed for processor tests. Overridden by --randomProcessorTest.");
  184. #if GR_TEST_UTILS
  185. static GrColor input_texel_color(int i, int j, SkScalar delta) {
  186. // Delta must be less than 0.5 to prevent over/underflow issues with the input color
  187. SkASSERT(delta <= 0.5);
  188. SkColor color = SkColorSetARGB((uint8_t)(i & 0xFF),
  189. (uint8_t)(j & 0xFF),
  190. (uint8_t)((i + j) & 0xFF),
  191. (uint8_t)((2 * j - i) & 0xFF));
  192. SkColor4f color4f = SkColor4f::FromColor(color);
  193. for (int i = 0; i < 4; i++) {
  194. if (color4f[i] > 0.5) {
  195. color4f[i] -= delta;
  196. } else {
  197. color4f[i] += delta;
  198. }
  199. }
  200. return color4f.premul().toBytes_RGBA();
  201. }
  202. void test_draw_op(GrContext* context,
  203. GrRenderTargetContext* rtc,
  204. std::unique_ptr<GrFragmentProcessor> fp,
  205. sk_sp<GrTextureProxy> inputDataProxy) {
  206. GrPaint paint;
  207. paint.addColorTextureProcessor(std::move(inputDataProxy), SkMatrix::I());
  208. paint.addColorFragmentProcessor(std::move(fp));
  209. paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
  210. auto op = GrFillRectOp::MakeNonAARect(context, std::move(paint), SkMatrix::I(),
  211. SkRect::MakeWH(rtc->width(), rtc->height()));
  212. rtc->addDrawOp(GrNoClip(), std::move(op));
  213. }
  214. // This assumes that the output buffer will be the same size as inputDataProxy
  215. void render_fp(GrContext* context, GrRenderTargetContext* rtc, GrFragmentProcessor* fp,
  216. sk_sp<GrTextureProxy> inputDataProxy, GrColor* buffer) {
  217. int width = inputDataProxy->width();
  218. int height = inputDataProxy->height();
  219. // test_draw_op needs to take ownership of an FP, so give it a clone that it can own
  220. test_draw_op(context, rtc, fp->clone(), inputDataProxy);
  221. memset(buffer, 0x0, sizeof(GrColor) * width * height);
  222. rtc->readPixels(SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
  223. buffer, 0, {0, 0});
  224. }
  225. /** Initializes the two test texture proxies that are available to the FP test factories. */
  226. bool init_test_textures(GrResourceProvider* resourceProvider,
  227. GrProxyProvider* proxyProvider,
  228. SkRandom* random,
  229. sk_sp<GrTextureProxy> proxies[2]) {
  230. static const int kTestTextureSize = 256;
  231. {
  232. // Put premul data into the RGBA texture that the test FPs can optionally use.
  233. std::unique_ptr<GrColor[]> rgbaData(new GrColor[kTestTextureSize * kTestTextureSize]);
  234. for (int y = 0; y < kTestTextureSize; ++y) {
  235. for (int x = 0; x < kTestTextureSize; ++x) {
  236. rgbaData[kTestTextureSize * y + x] = input_texel_color(
  237. random->nextULessThan(256), random->nextULessThan(256), 0.0f);
  238. }
  239. }
  240. SkImageInfo ii = SkImageInfo::Make(kTestTextureSize, kTestTextureSize,
  241. kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  242. SkPixmap pixmap(ii, rgbaData.get(), ii.minRowBytes());
  243. sk_sp<SkImage> img = SkImage::MakeRasterCopy(pixmap);
  244. proxies[0] = proxyProvider->createTextureProxy(img, GrRenderable::kNo, 1, SkBudgeted::kYes,
  245. SkBackingFit::kExact);
  246. proxies[0]->instantiate(resourceProvider);
  247. }
  248. {
  249. // Put random values into the alpha texture that the test FPs can optionally use.
  250. std::unique_ptr<uint8_t[]> alphaData(new uint8_t[kTestTextureSize * kTestTextureSize]);
  251. for (int y = 0; y < kTestTextureSize; ++y) {
  252. for (int x = 0; x < kTestTextureSize; ++x) {
  253. alphaData[kTestTextureSize * y + x] = random->nextULessThan(256);
  254. }
  255. }
  256. SkImageInfo ii = SkImageInfo::Make(kTestTextureSize, kTestTextureSize,
  257. kAlpha_8_SkColorType, kPremul_SkAlphaType);
  258. SkPixmap pixmap(ii, alphaData.get(), ii.minRowBytes());
  259. sk_sp<SkImage> img = SkImage::MakeRasterCopy(pixmap);
  260. proxies[1] = proxyProvider->createTextureProxy(img, GrRenderable::kNo, 1, SkBudgeted::kYes,
  261. SkBackingFit::kExact);
  262. proxies[1]->instantiate(resourceProvider);
  263. }
  264. return proxies[0] && proxies[1];
  265. }
  266. // Creates a texture of premul colors used as the output of the fragment processor that precedes
  267. // the fragment processor under test. Color values are those provided by input_texel_color().
  268. sk_sp<GrTextureProxy> make_input_texture(GrProxyProvider* proxyProvider, int width, int height,
  269. SkScalar delta) {
  270. std::unique_ptr<GrColor[]> data(new GrColor[width * height]);
  271. for (int y = 0; y < width; ++y) {
  272. for (int x = 0; x < height; ++x) {
  273. data.get()[width * y + x] = input_texel_color(x, y, delta);
  274. }
  275. }
  276. SkImageInfo ii = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  277. SkPixmap pixmap(ii, data.get(), ii.minRowBytes());
  278. sk_sp<SkImage> img = SkImage::MakeRasterCopy(pixmap);
  279. return proxyProvider->createTextureProxy(img, GrRenderable::kNo, 1, SkBudgeted::kYes,
  280. SkBackingFit::kExact);
  281. }
  282. bool log_surface_context(sk_sp<GrSurfaceContext> src, SkString* dst) {
  283. SkImageInfo ii = SkImageInfo::Make(src->width(), src->height(), kRGBA_8888_SkColorType,
  284. kPremul_SkAlphaType);
  285. SkBitmap bm;
  286. SkAssertResult(bm.tryAllocPixels(ii));
  287. SkAssertResult(src->readPixels(ii, bm.getPixels(), bm.rowBytes(), {0, 0}));
  288. return bitmap_to_base64_data_uri(bm, dst);
  289. }
  290. bool log_surface_proxy(GrContext* context, sk_sp<GrSurfaceProxy> src, SkString* dst) {
  291. // All the inputs are made from kRGBA_8888_SkColorType/kPremul_SkAlphaType bitmaps.
  292. sk_sp<GrSurfaceContext> sContext(context->priv().makeWrappedSurfaceContext(
  293. src, GrColorType::kRGBA_8888, kPremul_SkAlphaType));
  294. return log_surface_context(sContext, dst);
  295. }
  296. bool fuzzy_color_equals(const SkPMColor4f& c1, const SkPMColor4f& c2) {
  297. // With the loss of precision of rendering into 32-bit color, then estimating the FP's output
  298. // from that, it is not uncommon for a valid output to differ from estimate by up to 0.01
  299. // (really 1/128 ~ .0078, but frequently floating point issues make that tolerance a little
  300. // too unforgiving).
  301. static constexpr SkScalar kTolerance = 0.01f;
  302. for (int i = 0; i < 4; i++) {
  303. if (!SkScalarNearlyEqual(c1[i], c2[i], kTolerance)) {
  304. return false;
  305. }
  306. }
  307. return true;
  308. }
  309. int modulation_index(int channelIndex, bool alphaModulation) {
  310. return alphaModulation ? 3 : channelIndex;
  311. }
  312. // Given three input colors (color preceding the FP being tested), and the output of the FP, this
  313. // ensures that the out1 = fp * in1.a, out2 = fp * in2.a, and out3 = fp * in3.a, where fp is the
  314. // pre-modulated color that should not be changing across frames (FP's state doesn't change).
  315. //
  316. // When alphaModulation is false, this tests the very similar conditions that out1 = fp * in1,
  317. // etc. using per-channel modulation instead of modulation by just the input alpha channel.
  318. // - This estimates the pre-modulated fp color from one of the input/output pairs and confirms the
  319. // conditions hold for the other two pairs.
  320. bool legal_modulation(const GrColor& in1, const GrColor& in2, const GrColor& in3,
  321. const GrColor& out1, const GrColor& out2, const GrColor& out3,
  322. bool alphaModulation) {
  323. // Convert to floating point, which is the number space the FP operates in (more or less)
  324. SkPMColor4f in1f = SkPMColor4f::FromBytes_RGBA(in1);
  325. SkPMColor4f in2f = SkPMColor4f::FromBytes_RGBA(in2);
  326. SkPMColor4f in3f = SkPMColor4f::FromBytes_RGBA(in3);
  327. SkPMColor4f out1f = SkPMColor4f::FromBytes_RGBA(out1);
  328. SkPMColor4f out2f = SkPMColor4f::FromBytes_RGBA(out2);
  329. SkPMColor4f out3f = SkPMColor4f::FromBytes_RGBA(out3);
  330. // Reconstruct the output of the FP before the shader modulated its color with the input value.
  331. // When the original input is very small, it may cause the final output color to round
  332. // to 0, in which case we estimate the pre-modulated color using one of the stepped frames that
  333. // will then have a guaranteed larger channel value (since the offset will be added to it).
  334. SkPMColor4f fpPreModulation;
  335. for (int i = 0; i < 4; i++) {
  336. int modulationIndex = modulation_index(i, alphaModulation);
  337. if (in1f[modulationIndex] < 0.2f) {
  338. // Use the stepped frame
  339. fpPreModulation[i] = out2f[i] / in2f[modulationIndex];
  340. } else {
  341. fpPreModulation[i] = out1f[i] / in1f[modulationIndex];
  342. }
  343. }
  344. // With reconstructed pre-modulated FP output, derive the expected value of fp * input for each
  345. // of the transformed input colors.
  346. SkPMColor4f expected1 = alphaModulation ? (fpPreModulation * in1f.fA)
  347. : (fpPreModulation * in1f);
  348. SkPMColor4f expected2 = alphaModulation ? (fpPreModulation * in2f.fA)
  349. : (fpPreModulation * in2f);
  350. SkPMColor4f expected3 = alphaModulation ? (fpPreModulation * in3f.fA)
  351. : (fpPreModulation * in3f);
  352. return fuzzy_color_equals(out1f, expected1) &&
  353. fuzzy_color_equals(out2f, expected2) &&
  354. fuzzy_color_equals(out3f, expected3);
  355. }
  356. DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ProcessorOptimizationValidationTest, reporter, ctxInfo) {
  357. GrContext* context = ctxInfo.grContext();
  358. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  359. auto resourceProvider = context->priv().resourceProvider();
  360. using FPFactory = GrFragmentProcessorTestFactory;
  361. uint32_t seed = FLAGS_processorSeed;
  362. if (FLAGS_randomProcessorTest) {
  363. std::random_device rd;
  364. seed = rd();
  365. }
  366. // If a non-deterministic bot fails this test, check the output to see what seed it used, then
  367. // use --processorSeed <seed> (without --randomProcessorTest) to reproduce.
  368. SkRandom random(seed);
  369. // Make the destination context for the test.
  370. static constexpr int kRenderSize = 256;
  371. sk_sp<GrRenderTargetContext> rtc = context->priv().makeDeferredRenderTargetContext(
  372. SkBackingFit::kExact, kRenderSize, kRenderSize, GrColorType::kRGBA_8888, nullptr);
  373. sk_sp<GrTextureProxy> proxies[2];
  374. if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies)) {
  375. ERRORF(reporter, "Could not create test textures");
  376. return;
  377. }
  378. GrProcessorTestData testData(&random, context, rtc.get(), proxies);
  379. // Coverage optimization uses three frames with a linearly transformed input texture. The first
  380. // frame has no offset, second frames add .2 and .4, which should then be present as a fixed
  381. // difference between the frame outputs if the FP is properly following the modulation
  382. // requirements of the coverage optimization.
  383. static constexpr SkScalar kInputDelta = 0.2f;
  384. auto inputTexture1 = make_input_texture(proxyProvider, kRenderSize, kRenderSize, 0.0f);
  385. auto inputTexture2 = make_input_texture(proxyProvider, kRenderSize, kRenderSize, kInputDelta);
  386. auto inputTexture3 = make_input_texture(proxyProvider, kRenderSize, kRenderSize, 2*kInputDelta);
  387. // Encoded images are very verbose and this tests many potential images, so only export the
  388. // first failure (subsequent failures have a reasonable chance of being related).
  389. bool loggedFirstFailure = false;
  390. bool loggedFirstWarning = false;
  391. // Storage for the three frames required for coverage compatibility optimization. Each frame
  392. // uses the correspondingly numbered inputTextureX.
  393. std::unique_ptr<GrColor[]> readData1(new GrColor[kRenderSize * kRenderSize]);
  394. std::unique_ptr<GrColor[]> readData2(new GrColor[kRenderSize * kRenderSize]);
  395. std::unique_ptr<GrColor[]> readData3(new GrColor[kRenderSize * kRenderSize]);
  396. // Because processor factories configure themselves in random ways, this is not exhaustive.
  397. for (int i = 0; i < FPFactory::Count(); ++i) {
  398. int timesToInvokeFactory = 5;
  399. // Increase the number of attempts if the FP has child FPs since optimizations likely depend
  400. // on child optimizations being present.
  401. std::unique_ptr<GrFragmentProcessor> fp = FPFactory::MakeIdx(i, &testData);
  402. for (int j = 0; j < fp->numChildProcessors(); ++j) {
  403. // This value made a reasonable trade off between time and coverage when this test was
  404. // written.
  405. timesToInvokeFactory *= FPFactory::Count() / 2;
  406. }
  407. #if defined(__MSVC_RUNTIME_CHECKS)
  408. // This test is infuriatingly slow with MSVC runtime checks enabled
  409. timesToInvokeFactory = 1;
  410. #endif
  411. for (int j = 0; j < timesToInvokeFactory; ++j) {
  412. fp = FPFactory::MakeIdx(i, &testData);
  413. if (!fp->hasConstantOutputForConstantInput() && !fp->preservesOpaqueInput() &&
  414. !fp->compatibleWithCoverageAsAlpha()) {
  415. continue;
  416. }
  417. if (fp->compatibleWithCoverageAsAlpha()) {
  418. // 2nd and 3rd frames are only used when checking coverage optimization
  419. render_fp(context, rtc.get(), fp.get(), inputTexture2, readData2.get());
  420. render_fp(context, rtc.get(), fp.get(), inputTexture3, readData3.get());
  421. }
  422. // Draw base frame last so that rtc holds the original FP behavior if we need to
  423. // dump the image to the log.
  424. render_fp(context, rtc.get(), fp.get(), inputTexture1, readData1.get());
  425. if (0) { // Useful to see what FPs are being tested.
  426. SkString children;
  427. for (int c = 0; c < fp->numChildProcessors(); ++c) {
  428. if (!c) {
  429. children.append("(");
  430. }
  431. children.append(fp->childProcessor(c).name());
  432. children.append(c == fp->numChildProcessors() - 1 ? ")" : ", ");
  433. }
  434. SkDebugf("%s %s\n", fp->name(), children.c_str());
  435. }
  436. // This test has a history of being flaky on a number of devices. If an FP is logically
  437. // violating the optimizations, it's reasonable to expect it to violate requirements on
  438. // a large number of pixels in the image. Sporadic pixel violations are more indicative
  439. // of device errors and represents a separate problem.
  440. #if defined(SK_BUILD_FOR_SKQP)
  441. static constexpr int kMaxAcceptableFailedPixels = 0; // Strict when running as SKQP
  442. #else
  443. static constexpr int kMaxAcceptableFailedPixels = 2 * kRenderSize; // ~0.7% of the image
  444. #endif
  445. int failedPixelCount = 0;
  446. // Collect first optimization failure message, to be output later as a warning or an
  447. // error depending on whether the rendering "passed" or failed.
  448. SkString coverageMessage;
  449. SkString opaqueMessage;
  450. SkString constMessage;
  451. for (int y = 0; y < kRenderSize; ++y) {
  452. for (int x = 0; x < kRenderSize; ++x) {
  453. bool passing = true;
  454. GrColor input = input_texel_color(x, y, 0.0f);
  455. GrColor output = readData1.get()[y * kRenderSize + x];
  456. if (fp->compatibleWithCoverageAsAlpha()) {
  457. GrColor i2 = input_texel_color(x, y, kInputDelta);
  458. GrColor i3 = input_texel_color(x, y, 2 * kInputDelta);
  459. GrColor o2 = readData2.get()[y * kRenderSize + x];
  460. GrColor o3 = readData3.get()[y * kRenderSize + x];
  461. // A compatible processor is allowed to modulate either the input color or
  462. // just the input alpha.
  463. bool legalAlphaModulation = legal_modulation(input, i2, i3, output, o2, o3,
  464. /* alpha */ true);
  465. bool legalColorModulation = legal_modulation(input, i2, i3, output, o2, o3,
  466. /* alpha */ false);
  467. if (!legalColorModulation && !legalAlphaModulation) {
  468. passing = false;
  469. if (coverageMessage.isEmpty()) {
  470. coverageMessage.printf("\"Modulating\" processor %s did not match "
  471. "alpha-modulation nor color-modulation rules. "
  472. "Input: 0x%08x, Output: 0x%08x, pixel (%d, %d).",
  473. fp->name(), input, output, x, y);
  474. }
  475. }
  476. }
  477. SkPMColor4f input4f = SkPMColor4f::FromBytes_RGBA(input);
  478. SkPMColor4f output4f = SkPMColor4f::FromBytes_RGBA(output);
  479. SkPMColor4f expected4f;
  480. if (fp->hasConstantOutputForConstantInput(input4f, &expected4f)) {
  481. float rDiff = fabsf(output4f.fR - expected4f.fR);
  482. float gDiff = fabsf(output4f.fG - expected4f.fG);
  483. float bDiff = fabsf(output4f.fB - expected4f.fB);
  484. float aDiff = fabsf(output4f.fA - expected4f.fA);
  485. static constexpr float kTol = 4 / 255.f;
  486. if (rDiff > kTol || gDiff > kTol || bDiff > kTol || aDiff > kTol) {
  487. if (constMessage.isEmpty()) {
  488. passing = false;
  489. constMessage.printf("Processor %s claimed output for const input "
  490. "doesn't match actual output. Error: %f, Tolerance: %f, "
  491. "input: (%f, %f, %f, %f), actual: (%f, %f, %f, %f), "
  492. "expected(%f, %f, %f, %f)", fp->name(),
  493. SkTMax(rDiff, SkTMax(gDiff, SkTMax(bDiff, aDiff))), kTol,
  494. input4f.fR, input4f.fG, input4f.fB, input4f.fA,
  495. output4f.fR, output4f.fG, output4f.fB, output4f.fA,
  496. expected4f.fR, expected4f.fG, expected4f.fB, expected4f.fA);
  497. }
  498. }
  499. }
  500. if (input4f.isOpaque() && fp->preservesOpaqueInput() && !output4f.isOpaque()) {
  501. passing = false;
  502. if (opaqueMessage.isEmpty()) {
  503. opaqueMessage.printf("Processor %s claimed opaqueness is preserved but "
  504. "it is not. Input: 0x%08x, Output: 0x%08x.",
  505. fp->name(), input, output);
  506. }
  507. }
  508. if (!passing) {
  509. // Regardless of how many optimizations the pixel violates, count it as a
  510. // single bad pixel.
  511. failedPixelCount++;
  512. }
  513. }
  514. }
  515. // Finished analyzing the entire image, see if the number of pixel failures meets the
  516. // threshold for an FP violating the optimization requirements.
  517. if (failedPixelCount > kMaxAcceptableFailedPixels) {
  518. ERRORF(reporter, "Processor violated %d of %d pixels, seed: 0x%08x, processor: %s"
  519. ", first failing pixel details are below:",
  520. failedPixelCount, kRenderSize * kRenderSize, seed,
  521. fp->dumpInfo().c_str());
  522. // Print first failing pixel's details.
  523. if (!coverageMessage.isEmpty()) {
  524. ERRORF(reporter, coverageMessage.c_str());
  525. }
  526. if (!constMessage.isEmpty()) {
  527. ERRORF(reporter, constMessage.c_str());
  528. }
  529. if (!opaqueMessage.isEmpty()) {
  530. ERRORF(reporter, opaqueMessage.c_str());
  531. }
  532. if (!loggedFirstFailure) {
  533. // Print with ERRORF to make sure the encoded image is output
  534. SkString input;
  535. log_surface_proxy(context, inputTexture1, &input);
  536. SkString output;
  537. log_surface_context(rtc, &output);
  538. ERRORF(reporter, "Input image: %s\n\n"
  539. "===========================================================\n\n"
  540. "Output image: %s\n", input.c_str(), output.c_str());
  541. loggedFirstFailure = true;
  542. }
  543. } else if(failedPixelCount > 0) {
  544. // Don't trigger an error, but don't just hide the failures either.
  545. INFOF(reporter, "Processor violated %d of %d pixels (below error threshold), seed: "
  546. "0x%08x, processor: %s", failedPixelCount, kRenderSize * kRenderSize,
  547. seed, fp->dumpInfo().c_str());
  548. if (!coverageMessage.isEmpty()) {
  549. INFOF(reporter, coverageMessage.c_str());
  550. }
  551. if (!constMessage.isEmpty()) {
  552. INFOF(reporter, constMessage.c_str());
  553. }
  554. if (!opaqueMessage.isEmpty()) {
  555. INFOF(reporter, opaqueMessage.c_str());
  556. }
  557. if (!loggedFirstWarning) {
  558. SkString input;
  559. log_surface_proxy(context, inputTexture1, &input);
  560. SkString output;
  561. log_surface_context(rtc, &output);
  562. INFOF(reporter, "Input image: %s\n\n"
  563. "===========================================================\n\n"
  564. "Output image: %s\n", input.c_str(), output.c_str());
  565. loggedFirstWarning = true;
  566. }
  567. }
  568. }
  569. }
  570. }
  571. // Tests that fragment processors returned by GrFragmentProcessor::clone() are equivalent to their
  572. // progenitors.
  573. DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(ProcessorCloneTest, reporter, ctxInfo) {
  574. GrContext* context = ctxInfo.grContext();
  575. GrProxyProvider* proxyProvider = context->priv().proxyProvider();
  576. auto resourceProvider = context->priv().resourceProvider();
  577. SkRandom random;
  578. // Make the destination context for the test.
  579. static constexpr int kRenderSize = 1024;
  580. sk_sp<GrRenderTargetContext> rtc = context->priv().makeDeferredRenderTargetContext(
  581. SkBackingFit::kExact, kRenderSize, kRenderSize, GrColorType::kRGBA_8888, nullptr);
  582. sk_sp<GrTextureProxy> proxies[2];
  583. if (!init_test_textures(resourceProvider, proxyProvider, &random, proxies)) {
  584. ERRORF(reporter, "Could not create test textures");
  585. return;
  586. }
  587. GrProcessorTestData testData(&random, context, rtc.get(), proxies);
  588. auto inputTexture = make_input_texture(proxyProvider, kRenderSize, kRenderSize, 0.0f);
  589. std::unique_ptr<GrColor[]> readData1(new GrColor[kRenderSize * kRenderSize]);
  590. std::unique_ptr<GrColor[]> readData2(new GrColor[kRenderSize * kRenderSize]);
  591. auto readInfo = SkImageInfo::Make(kRenderSize, kRenderSize, kRGBA_8888_SkColorType,
  592. kPremul_SkAlphaType);
  593. // Because processor factories configure themselves in random ways, this is not exhaustive.
  594. for (int i = 0; i < GrFragmentProcessorTestFactory::Count(); ++i) {
  595. static constexpr int kTimesToInvokeFactory = 10;
  596. for (int j = 0; j < kTimesToInvokeFactory; ++j) {
  597. auto fp = GrFragmentProcessorTestFactory::MakeIdx(i, &testData);
  598. auto clone = fp->clone();
  599. if (!clone) {
  600. ERRORF(reporter, "Clone of processor %s failed.", fp->name());
  601. continue;
  602. }
  603. const char* name = fp->name();
  604. REPORTER_ASSERT(reporter, !strcmp(fp->name(), clone->name()));
  605. REPORTER_ASSERT(reporter, fp->compatibleWithCoverageAsAlpha() ==
  606. clone->compatibleWithCoverageAsAlpha());
  607. REPORTER_ASSERT(reporter, fp->isEqual(*clone));
  608. REPORTER_ASSERT(reporter, fp->preservesOpaqueInput() == clone->preservesOpaqueInput());
  609. REPORTER_ASSERT(reporter, fp->hasConstantOutputForConstantInput() ==
  610. clone->hasConstantOutputForConstantInput());
  611. REPORTER_ASSERT(reporter, fp->numChildProcessors() == clone->numChildProcessors());
  612. REPORTER_ASSERT(reporter, fp->usesLocalCoords() == clone->usesLocalCoords());
  613. // Draw with original and read back the results.
  614. render_fp(context, rtc.get(), fp.get(), inputTexture, readData1.get());
  615. // Draw with clone and read back the results.
  616. render_fp(context, rtc.get(), clone.get(), inputTexture, readData2.get());
  617. // Check that the results are the same.
  618. bool passing = true;
  619. for (int y = 0; y < kRenderSize && passing; ++y) {
  620. for (int x = 0; x < kRenderSize && passing; ++x) {
  621. int idx = y * kRenderSize + x;
  622. if (readData1[idx] != readData2[idx]) {
  623. ERRORF(reporter,
  624. "Processor %s made clone produced different output. "
  625. "Input color: 0x%08x, Original Output Color: 0x%08x, "
  626. "Clone Output Color: 0x%08x..",
  627. name, input_texel_color(x, y, 0.0f), readData1[idx], readData2[idx]);
  628. passing = false;
  629. }
  630. }
  631. }
  632. }
  633. }
  634. }
  635. #endif // GR_TEST_UTILS