diff options
author | Robert Phillips <robertphillips@google.com> | 2018-02-01 09:10:04 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-02-01 15:00:53 +0000 |
commit | 620003692923dc6c6df5a1b66288988b6783a69f (patch) | |
tree | 5010067f4d26fb23f28964e74b5e37c38e3dddc3 /include/private | |
parent | 5f9ee7cc53d28c8ff2d000436bfee195c493ccdf (diff) |
Implement GPU/OpList DDLs
This relies on https://skia-review.googlesource.com/c/skia/+/102101 (Add SkSurface_Gpu::MakeWrappedRenderTarget method) landing first
TBR=bsalomon@google.com
Change-Id: I4d2d66af5800407f638ef32d7b19ce49084bd4e4
Reviewed-on: https://skia-review.googlesource.com/102263
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'include/private')
-rw-r--r-- | include/private/GrOpList.h | 194 | ||||
-rw-r--r-- | include/private/GrSurfaceProxyRef.h | 71 | ||||
-rw-r--r-- | include/private/SkDeferredDisplayList.h | 54 | ||||
-rw-r--r-- | include/private/SkSurfaceCharacterization.h | 10 |
4 files changed, 318 insertions, 11 deletions
diff --git a/include/private/GrOpList.h b/include/private/GrOpList.h new file mode 100644 index 0000000000..c9abd6d4e5 --- /dev/null +++ b/include/private/GrOpList.h @@ -0,0 +1,194 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrOpList_DEFINED +#define GrOpList_DEFINED + +#include "GrColor.h" +#include "GrSurfaceProxyRef.h" +#include "GrTextureProxy.h" +#include "SkRefCnt.h" +#include "SkTDArray.h" + + +// Turn on/off the explicit distribution of GPU resources at flush time +#ifndef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION + #define SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION +#endif + +// Turn on/off the sorting of opLists at flush time +#ifndef SK_DISABLE_RENDER_TARGET_SORTING + #define SK_DISABLE_RENDER_TARGET_SORTING +#endif + +class GrAuditTrail; +class GrCaps; +class GrOpFlushState; +class GrRenderTargetOpList; +class GrResourceAllocator; +class GrResourceProvider; +class GrSurfaceProxy; +class GrTextureOpList; + +struct SkIPoint; +struct SkIRect; + +class GrOpList : public SkRefCnt { +public: + GrOpList(GrResourceProvider*, GrSurfaceProxy*, GrAuditTrail*); + ~GrOpList() override; + + // These four methods are invoked at flush time + bool instantiate(GrResourceProvider* resourceProvider); + // Instantiates any "threaded" texture proxies that are being prepared elsewhere + void instantiateDeferredProxies(GrResourceProvider* resourceProvider); + void prepare(GrOpFlushState* flushState); + bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); } + + virtual bool copySurface(const GrCaps& caps, + GrSurfaceProxy* dst, + GrSurfaceProxy* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint) = 0; + + virtual void makeClosed(const GrCaps&) { + if (!this->isClosed()) { + this->setFlag(kClosed_Flag); + fTarget.removeRef(); + } + } + + // Called when this class will survive a flush and needs to truncate its ops and start over. + // TODO: ultimately it should be invalid for an op list to survive a flush. + // https://bugs.chromium.org/p/skia/issues/detail?id=7111 + virtual void endFlush(); + + bool isClosed() const { return this->isSetFlag(kClosed_Flag); } + + /* + * Notify this GrOpList that it relies on the contents of 'dependedOn' + */ + void addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps); + + /* + * Does this opList depend on 'dependedOn'? + */ + bool dependsOn(GrOpList* dependedOn) const { + for (int i = 0; i < fDependencies.count(); ++i) { + if (fDependencies[i] == dependedOn) { + return true; + } + } + + return false; + } + + /* + * Safely cast this GrOpList to a GrTextureOpList (if possible). + */ + virtual GrTextureOpList* asTextureOpList() { return nullptr; } + + /* + * Safely case this GrOpList to a GrRenderTargetOpList (if possible). + */ + virtual GrRenderTargetOpList* asRenderTargetOpList() { return nullptr; } + + uint32_t uniqueID() const { return fUniqueID; } + + /* + * Dump out the GrOpList dependency DAG + */ + SkDEBUGCODE(virtual void dump() const;) + + SkDEBUGCODE(virtual int numOps() const = 0;) + SkDEBUGCODE(virtual int numClips() const { return 0; }) + + // TODO: it would be nice for this to be hidden + void setStencilLoadOp(GrLoadOp loadOp) { fStencilLoadOp = loadOp; } + +protected: + SkDEBUGCODE(bool isInstantiated() const;) + + GrSurfaceProxyRef fTarget; + GrAuditTrail* fAuditTrail; + + GrLoadOp fColorLoadOp = GrLoadOp::kLoad; + GrColor fLoadClearColor = 0x0; + GrLoadOp fStencilLoadOp = GrLoadOp::kLoad; + + // List of texture proxies whose contents are being prepared on a worker thread + SkTArray<GrTextureProxy*, true> fDeferredProxies; + +private: + friend class GrDrawingManager; // for resetFlag, TopoSortTraits & gatherProxyIntervals + + // Remove all Ops which reference proxies that have not been instantiated. + virtual void purgeOpsWithUninstantiatedProxies() = 0; + + // Feed proxy usage intervals to the GrResourceAllocator class + virtual void gatherProxyIntervals(GrResourceAllocator*) const = 0; + + static uint32_t CreateUniqueID(); + + enum Flags { + kClosed_Flag = 0x01, //!< This GrOpList can't accept any more ops + + kWasOutput_Flag = 0x02, //!< Flag for topological sorting + kTempMark_Flag = 0x04, //!< Flag for topological sorting + }; + + void setFlag(uint32_t flag) { + fFlags |= flag; + } + + void resetFlag(uint32_t flag) { + fFlags &= ~flag; + } + + bool isSetFlag(uint32_t flag) const { + return SkToBool(fFlags & flag); + } + + struct TopoSortTraits { + static void Output(GrOpList* dt, int /* index */) { + dt->setFlag(GrOpList::kWasOutput_Flag); + } + static bool WasOutput(const GrOpList* dt) { + return dt->isSetFlag(GrOpList::kWasOutput_Flag); + } + static void SetTempMark(GrOpList* dt) { + dt->setFlag(GrOpList::kTempMark_Flag); + } + static void ResetTempMark(GrOpList* dt) { + dt->resetFlag(GrOpList::kTempMark_Flag); + } + static bool IsTempMarked(const GrOpList* dt) { + return dt->isSetFlag(GrOpList::kTempMark_Flag); + } + static int NumDependencies(const GrOpList* dt) { + return dt->fDependencies.count(); + } + static GrOpList* Dependency(GrOpList* dt, int index) { + return dt->fDependencies[index]; + } + }; + + virtual void onPrepare(GrOpFlushState* flushState) = 0; + virtual bool onExecute(GrOpFlushState* flushState) = 0; + + void addDependency(GrOpList* dependedOn); + + uint32_t fUniqueID; + uint32_t fFlags; + + // 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies' + SkSTArray<1, GrOpList*, true> fDependencies; + + typedef SkRefCnt INHERITED; +}; + +#endif diff --git a/include/private/GrSurfaceProxyRef.h b/include/private/GrSurfaceProxyRef.h new file mode 100644 index 0000000000..2319357251 --- /dev/null +++ b/include/private/GrSurfaceProxyRef.h @@ -0,0 +1,71 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrSurfaceProxyRef_DEFINED +#define GrSurfaceProxyRef_DEFINED + +#include "GrTypesPriv.h" + +class GrSurfaceProxy; + +class GrSurfaceProxyRef : SkNoncopyable { +public: + virtual ~GrSurfaceProxyRef(); + + GrSurfaceProxy* get() const { return fProxy; } + + /** Does this object own a pending read or write on the resource it is wrapping. */ + bool ownsPendingIO() const { return fPendingIO; } + + /** What type of IO does this represent? This is independent of whether a normal ref or a + pending IO is currently held. */ + GrIOType ioType() const { return fIOType; } + + /** Shortcut for calling setProxy() with NULL. It cannot be called after markingPendingIO + is called. */ + void reset(); + +protected: + GrSurfaceProxyRef(); + + /** ioType expresses what type of IO operations will be marked as + pending on the resource when markPendingIO is called. */ + GrSurfaceProxyRef(sk_sp<GrSurfaceProxy>, GrIOType); + + /** ioType expresses what type of IO operations will be marked as + pending on the resource when markPendingIO is called. */ + void setProxy(sk_sp<GrSurfaceProxy>, GrIOType); + +private: + /** Called by owning GrProgramElement when the program element is first scheduled for + execution. It can only be called once. */ + void markPendingIO() const; + + /** Called when the program element/draw state is no longer owned by GrOpList-client code. + This lets the cache know that the drawing code will no longer schedule additional reads or + writes to the resource using the program element or draw state. It can only be called once. + */ + void removeRef() const; + + /** Called to indicate that the previous pending IO is complete. Useful when the owning object + still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously + pending executions have been complete. Can only be called if removeRef() was not previously + called. */ + void pendingIOComplete() const; + + friend class GrResourceIOProcessor; + friend class GrOpList; // for setProxy + + GrSurfaceProxy* fProxy; + mutable bool fOwnRef; + mutable bool fPendingIO; + GrIOType fIOType; + + typedef SkNoncopyable INHERITED; +}; + +#endif diff --git a/include/private/SkDeferredDisplayList.h b/include/private/SkDeferredDisplayList.h index 392a952a1d..a3517bb6a0 100644 --- a/include/private/SkDeferredDisplayList.h +++ b/include/private/SkDeferredDisplayList.h @@ -10,7 +10,14 @@ #include "SkSurfaceCharacterization.h" -class SkImage; // TODO: rm this since it is just for the temporary placeholder implementation +#if SK_SUPPORT_GPU +#include "GrOpList.h" +#endif + +#ifdef SK_RASTER_RECORDER_IMPLEMENTATION +class SkImage; // DDL TODO: rm this since it is just for the temporary placeholder implementation +#endif + class SkSurface; /* @@ -21,24 +28,55 @@ class SkSurface; */ class SkDeferredDisplayList { public: - SkDeferredDisplayList(const SkSurfaceCharacterization& characterization, - sk_sp<SkImage> image) // TODO rm this parameter + +#ifdef SK_RASTER_RECORDER_IMPLEMENTATION + SkDeferredDisplayList(const SkSurfaceCharacterization& characterization, sk_sp<SkImage> image) : fCharacterization(characterization) , fImage(std::move(image)) { } + // DDL TODO: remove this. It is just scaffolding to get something up & running + bool draw(SkSurface*) const; +#endif + +#if SK_SUPPORT_GPU + // This object is the source from which the lazy proxy backing the DDL will pull its backing + // texture when the DDL is replayed. It has to be separately ref counted bc the lazy proxy + // can outlive the DDL. + class LazyProxyData : public SkRefCnt { + public: + // Upon being replayed - this field will be filled in (by the DrawingManager) with the proxy + // backing the destination SkSurface. Note that, since there is no good place to clear it + // it can become a dangling pointer. + GrRenderTargetProxy* fReplayDest = nullptr; + }; +#else + class LazyProxyData : public SkRefCnt {}; +#endif + + SkDeferredDisplayList(const SkSurfaceCharacterization& characterization, + sk_sp<LazyProxyData>); + const SkSurfaceCharacterization& characterization() const { return fCharacterization; } - // TODO: remove this. It is just scaffolding to get something up & running - bool draw(SkSurface*) const; - private: + friend class GrDrawingManager; // for access to 'fOpLists' and 'fLazyProxyData' + friend class SkDeferredDisplayListRecorder; // for access to 'fLazyProxyData' + const SkSurfaceCharacterization fCharacterization; - // TODO: actually store the GPU opLists - sk_sp<SkImage> fImage; +#ifdef SK_RASTER_RECORDER_IMPLEMENTATION + sk_sp<SkImage> fImage; +#else + +#if SK_SUPPORT_GPU + SkTArray<sk_sp<GrOpList>> fOpLists; +#endif + sk_sp<LazyProxyData> fLazyProxyData; + +#endif }; #endif diff --git a/include/private/SkSurfaceCharacterization.h b/include/private/SkSurfaceCharacterization.h index 40be90c685..07838968b9 100644 --- a/include/private/SkSurfaceCharacterization.h +++ b/include/private/SkSurfaceCharacterization.h @@ -10,14 +10,18 @@ #include "GrTypes.h" +#include "SkColorSpace.h" +#include "SkRefCnt.h" #include "SkSurfaceProps.h" class SkColorSpace; -#if SK_SUPPORT_GPU -#include "GrTypesPriv.h" +// This define can be used to swap between the default (raster) DDL implementation and the +// gpu implementation. +#define SK_RASTER_RECORDER_IMPLEMENTATION 1 -class GrContextThreadSafeProxy; +#if SK_SUPPORT_GPU +#include "GrContext.h" /** \class SkSurfaceCharacterization A surface characterization contains all the information Ganesh requires to makes its internal |