diff options
author | Chris Dalton <csmartdalton@google.com> | 2017-10-06 16:27:32 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-10-06 22:48:59 +0000 |
commit | cc604e5e9e33030a3033d2c6cc22e7759ab4d42e (patch) | |
tree | a6df3bced36be543445e95d5516b395356d563ea | |
parent | 4a6a732352fcb1445802dc95a477a943a31a9ac4 (diff) |
CCPR: Add workaround for PowerVR crash
Bug: skia:
Change-Id: Icd00f81fda5366813f9c959fdc91b0415894cbfc
Reviewed-on: https://skia-review.googlesource.com/55360
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
-rw-r--r-- | gn/tests.gni | 1 | ||||
-rw-r--r-- | src/gpu/GrCaps.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 12 | ||||
-rw-r--r-- | tests/GrCCPRTest.cpp | 101 |
6 files changed, 131 insertions, 4 deletions
diff --git a/gn/tests.gni b/gn/tests.gni index 34c10b53f1..a6135ed9c8 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -87,6 +87,7 @@ tests_sources = [ "$_tests/GpuSampleLocationsTest.cpp", "$_tests/GradientTest.cpp", "$_tests/GrAllocatorTest.cpp", + "$_tests/GrCCPRTest.cpp", "$_tests/GrContextAbandonTest.cpp", "$_tests/GrContextFactoryTest.cpp", "$_tests/GrMemoryPoolTest.cpp", diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp index a0e435a9c3..f4c7de7304 100644 --- a/src/gpu/GrCaps.cpp +++ b/src/gpu/GrCaps.cpp @@ -149,6 +149,8 @@ void GrCaps::dumpJSON(SkJSONWriter* writer) const { writer->appendBool("Cross context texture support", fCrossContextTextureSupport); writer->appendBool("Draw Instead of Clear [workaround]", fUseDrawInsteadOfClear); + writer->appendBool("Blacklist Coverage Counting Path Renderer [workaround]", + fBlacklistCoverageCounting); writer->appendBool("Prefer VRAM Use over flushes [workaround]", fPreferVRAMUseOverFlushes); if (this->advancedBlendEquationSupport()) { diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 3b401e65a1..088e5cbbdd 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -62,6 +62,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fRequiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines = false; fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag; + fMaxInstancesPerDrawArraysWithoutCrashing = 0; fShaderCaps.reset(new GrShaderCaps(contextOptions)); @@ -595,6 +596,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, fRequiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines = true; } + // Our Chromebook with kPowerVRRogue_GrGLRenderer seems to crash when glDrawArraysInstanced is + // given 1 << 15 or more instances. + if (kPowerVRRogue_GrGLRenderer == ctxInfo.renderer()) { + fMaxInstancesPerDrawArraysWithoutCrashing = 0x7fff; + } + // Texture uploads sometimes seem to be ignored to textures bound to FBOS on Tegra3. if (kTegra3_GrGLRenderer == ctxInfo.renderer()) { fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO = true; @@ -1374,6 +1381,8 @@ void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const { fDisallowTexSubImageForUnormConfigTexturesEverBoundToFBO); writer->appendBool("Intermediate texture for all updates of textures bound to FBOs", fUseDrawInsteadOfAllRenderTargetWrites); + writer->appendBool("Max instances per glDrawArraysInstanced without crashing (or zero)", + fMaxInstancesPerDrawArraysWithoutCrashing); writer->beginArray("configs"); diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 68cbc9bf16..5140aeea2f 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -399,6 +399,15 @@ public: return fRequiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines; } + // Returns the observed maximum number of instances the driver can handle in a single call to + // glDrawArraysInstanced without crashing, or 'pendingInstanceCount' if this + // workaround is not necessary. + // NOTE: the return value may be larger than pendingInstanceCount. + int maxInstancesPerDrawArraysWithoutCrashing(int pendingInstanceCount) const { + return fMaxInstancesPerDrawArraysWithoutCrashing ? fMaxInstancesPerDrawArraysWithoutCrashing + : pendingInstanceCount; + } + bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, bool* rectsMustMatch, bool* disallowSubrect) const override; @@ -479,6 +488,7 @@ private: bool fRequiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines : 1; uint32_t fBlitFramebufferFlags; + int fMaxInstancesPerDrawArraysWithoutCrashing; /** Number type of the components (with out considering number of bits.) */ enum FormatType { diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 8190206d8f..10dabe4629 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2619,10 +2619,14 @@ void GrGLGpu::sendInstancedMeshToGpu(const GrPrimitiveProcessor& primProc, GrPri int vertexCount, int baseVertex, const GrBuffer* instanceBuffer, int instanceCount, int baseInstance) { - const GrGLenum glPrimType = gr_primitive_type_to_gl_mode(primitiveType); - this->setupGeometry(primProc, nullptr, vertexBuffer, 0, instanceBuffer, baseInstance); - GL_CALL(DrawArraysInstanced(glPrimType, baseVertex, vertexCount, instanceCount)); - fStats.incNumDraws(); + GrGLenum glPrimType = gr_primitive_type_to_gl_mode(primitiveType); + int maxInstances = this->glCaps().maxInstancesPerDrawArraysWithoutCrashing(instanceCount); + for (int i = 0; i < instanceCount; i += maxInstances) { + this->setupGeometry(primProc, nullptr, vertexBuffer, 0, instanceBuffer, baseInstance + i); + GL_CALL(DrawArraysInstanced(glPrimType, baseVertex, vertexCount, + SkTMin(instanceCount - i, maxInstances))); + fStats.incNumDraws(); + } } void GrGLGpu::sendIndexedInstancedMeshToGpu(const GrPrimitiveProcessor& primProc, diff --git a/tests/GrCCPRTest.cpp b/tests/GrCCPRTest.cpp new file mode 100644 index 0000000000..d8be726d6e --- /dev/null +++ b/tests/GrCCPRTest.cpp @@ -0,0 +1,101 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkTypes.h" +#include "Test.h" + +#if SK_SUPPORT_GPU + +#include "GrContext.h" +#include "GrContextPriv.h" +#include "GrClip.h" +#include "GrRenderTargetContext.h" +#include "GrRenderTargetContextPriv.h" +#include "GrShape.h" +#include "GrPathRenderer.h" +#include "GrPaint.h" +#include "SkMatrix.h" +#include "SkRect.h" +#include "ccpr/GrCoverageCountingPathRenderer.h" +#include <cmath> + +static constexpr int kCanvasSize = 100; + +class CCPRPathDrawer { +public: + CCPRPathDrawer(GrContext* ctx) + : fCtx(ctx) + , fCCPR(GrCoverageCountingPathRenderer::CreateIfSupported(*fCtx->caps())) + , fRTC(fCtx->makeDeferredRenderTargetContext(SkBackingFit::kExact, kCanvasSize, + kCanvasSize, kRGBA_8888_GrPixelConfig, + nullptr)) { + if (fCCPR) { + fCtx->contextPriv().addOnFlushCallbackObject(fCCPR.get()); + } + } + + ~CCPRPathDrawer() { + if (fCCPR) { + fCtx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(fCCPR.get()); + } + } + + bool valid() { return fCCPR && fRTC; } + + void clear() { fRTC->clear(nullptr, 0, true); } + + void drawPath(const SkPath& path, GrColor4f color = GrColor4f(0, 1, 0, 1)) { + GrPaint paint; + paint.setColor4f(color); + GrNoClip noClip; + SkIRect clipBounds = SkIRect::MakeWH(kCanvasSize, kCanvasSize); + SkMatrix matrix = SkMatrix::I(); + GrShape shape(path); + fCCPR->drawPath({fCtx, std::move(paint), &GrUserStencilSettings::kUnused, fRTC.get(), + &noClip, &clipBounds, &matrix, &shape, GrAAType::kCoverage, false}); + } + + void flush() { + fCtx->flush(); + } + +private: + GrContext* const fCtx; + sk_sp<GrCoverageCountingPathRenderer> fCCPR; + sk_sp<GrRenderTargetContext> fRTC; +}; + +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrCCPRTest, reporter, ctxInfo) { + GrContext* const ctx = ctxInfo.grContext(); + if (!GrCoverageCountingPathRenderer::IsSupported(*ctx->caps())) { + return; + } + + CCPRPathDrawer ccpr(ctx); + if (!ccpr.valid()) { + ERRORF(reporter, "could not create render target context for ccpr."); + return; + } + + // Test very busy paths. + static constexpr int kNumBusyVerbs = 1 << 17; + ccpr.clear(); + SkPath busyPath; + busyPath.moveTo(0, 0); // top left + busyPath.lineTo(kCanvasSize, kCanvasSize); // bottom right + for (int i = 2; i < kNumBusyVerbs; ++i) { + float offset = i * ((float)kCanvasSize / kNumBusyVerbs); + busyPath.lineTo(kCanvasSize - offset, kCanvasSize + offset); // offscreen + } + ccpr.drawPath(busyPath); + + ccpr.flush(); // If this doesn't crash, the test passed. + // If it does, maybe fiddle with fMaxInstancesPerDrawArraysWithoutCrashing in your + // platform's GrGLCaps. +} + +#endif |