Home | History | Annotate | Download | only in gpu
      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 
      8 #include "GrOpList.h"
      9 
     10 #include "GrContext.h"
     11 #include "GrDeferredProxyUploader.h"
     12 #include "GrMemoryPool.h"
     13 #include "GrRenderTargetPriv.h"
     14 #include "GrSurfaceProxy.h"
     15 #include "GrTextureProxyPriv.h"
     16 #include <atomic>
     17 
     18 uint32_t GrOpList::CreateUniqueID() {
     19     static std::atomic<uint32_t> nextID{1};
     20     uint32_t id;
     21     do {
     22         id = nextID++;
     23     } while (id == SK_InvalidUniqueID);
     24     return id;
     25 }
     26 
     27 GrOpList::GrOpList(GrResourceProvider* resourceProvider, sk_sp<GrOpMemoryPool> opMemoryPool,
     28                    GrSurfaceProxy* surfaceProxy, GrAuditTrail* auditTrail)
     29         : fOpMemoryPool(std::move(opMemoryPool))
     30         , fAuditTrail(auditTrail)
     31         , fUniqueID(CreateUniqueID())
     32         , fFlags(0) {
     33     SkASSERT(fOpMemoryPool);
     34     fTarget.setProxy(sk_ref_sp(surfaceProxy), kWrite_GrIOType);
     35     fTarget.get()->setLastOpList(this);
     36 
     37     if (resourceProvider && !resourceProvider->explicitlyAllocateGPUResources()) {
     38         // MDB TODO: remove this! We are currently moving to having all the ops that target
     39         // the RT as a dest (e.g., clear, etc.) rely on the opList's 'fTarget' pointer
     40         // for the IO Ref. This works well but until they are all swapped over (and none
     41         // are pre-emptively instantiating proxies themselves) we need to instantiate
     42         // here so that the GrSurfaces are created in an order that preserves the GrSurface
     43         // re-use assumptions.
     44         fTarget.get()->instantiate(resourceProvider);
     45     }
     46 
     47     fTarget.markPendingIO();
     48 }
     49 
     50 GrOpList::~GrOpList() {
     51     if (fTarget.get() && this == fTarget.get()->getLastOpList()) {
     52         // Ensure the target proxy doesn't keep hold of a dangling back pointer.
     53         fTarget.get()->setLastOpList(nullptr);
     54     }
     55 }
     56 
     57 bool GrOpList::instantiate(GrResourceProvider* resourceProvider) {
     58     return SkToBool(fTarget.get()->instantiate(resourceProvider));
     59 }
     60 
     61 void GrOpList::endFlush() {
     62     if (fTarget.get() && this == fTarget.get()->getLastOpList()) {
     63         fTarget.get()->setLastOpList(nullptr);
     64     }
     65 
     66     fTarget.reset();
     67     fDeferredProxies.reset();
     68     fAuditTrail = nullptr;
     69 }
     70 
     71 void GrOpList::instantiateDeferredProxies(GrResourceProvider* resourceProvider) {
     72     for (int i = 0; i < fDeferredProxies.count(); ++i) {
     73         if (resourceProvider->explicitlyAllocateGPUResources()) {
     74             SkASSERT(fDeferredProxies[i]->isInstantiated());
     75         } else {
     76             fDeferredProxies[i]->instantiate(resourceProvider);
     77         }
     78     }
     79 }
     80 
     81 void GrOpList::prepare(GrOpFlushState* flushState) {
     82     for (int i = 0; i < fDeferredProxies.count(); ++i) {
     83         fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
     84     }
     85 
     86     this->onPrepare(flushState);
     87 }
     88 
     89 // Add a GrOpList-based dependency
     90 void GrOpList::addDependency(GrOpList* dependedOn) {
     91     SkASSERT(!dependedOn->dependsOn(this));  // loops are bad
     92 
     93     if (this->dependsOn(dependedOn)) {
     94         return;  // don't add duplicate dependencies
     95     }
     96 
     97     fDependencies.push_back(dependedOn);
     98     dependedOn->addDependent(this);
     99 
    100     SkDEBUGCODE(this->validate());
    101 }
    102 
    103 // Convert from a GrSurface-based dependency to a GrOpList one
    104 void GrOpList::addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps) {
    105     if (dependedOn->getLastOpList()) {
    106         // If it is still receiving dependencies, this GrOpList shouldn't be closed
    107         SkASSERT(!this->isClosed());
    108 
    109         GrOpList* opList = dependedOn->getLastOpList();
    110         if (opList == this) {
    111             // self-read - presumably for dst reads. We can't make it closed in the self-read case.
    112         } else {
    113             this->addDependency(opList);
    114 
    115             // We are closing 'opList' here bc the current contents of it are what 'this' opList
    116             // depends on. We need a break in 'opList' so that the usage of that state has a
    117             // chance to execute.
    118             opList->makeClosed(caps);
    119         }
    120     }
    121 
    122     if (GrTextureProxy* textureProxy = dependedOn->asTextureProxy()) {
    123         if (textureProxy->texPriv().isDeferred()) {
    124             fDeferredProxies.push_back(textureProxy);
    125         }
    126     }
    127 }
    128 
    129 bool GrOpList::dependsOn(const GrOpList* dependedOn) const {
    130     for (int i = 0; i < fDependencies.count(); ++i) {
    131         if (fDependencies[i] == dependedOn) {
    132             return true;
    133         }
    134     }
    135 
    136     return false;
    137 }
    138 
    139 
    140 void GrOpList::addDependent(GrOpList* dependent) {
    141     fDependents.push_back(dependent);
    142 }
    143 
    144 #ifdef SK_DEBUG
    145 bool GrOpList::isDependedent(const GrOpList* dependent) const {
    146     for (int i = 0; i < fDependents.count(); ++i) {
    147         if (fDependents[i] == dependent) {
    148             return true;
    149         }
    150     }
    151 
    152     return false;
    153 }
    154 
    155 void GrOpList::validate() const {
    156     // TODO: check for loops and duplicates
    157 
    158     for (int i = 0; i < fDependencies.count(); ++i) {
    159         SkASSERT(fDependencies[i]->isDependedent(this));
    160     }
    161 }
    162 #endif
    163 
    164 bool GrOpList::isInstantiated() const { return fTarget.get()->isInstantiated(); }
    165 
    166 void GrOpList::closeThoseWhoDependOnMe(const GrCaps& caps) {
    167     for (int i = 0; i < fDependents.count(); ++i) {
    168         if (!fDependents[i]->isClosed()) {
    169             fDependents[i]->makeClosed(caps);
    170         }
    171     }
    172 }
    173 
    174 bool GrOpList::isFullyInstantiated() const {
    175     if (!this->isInstantiated()) {
    176         return false;
    177     }
    178 
    179     GrSurfaceProxy* proxy = fTarget.get();
    180     bool needsStencil = proxy->asRenderTargetProxy()
    181                                         ? proxy->asRenderTargetProxy()->needsStencil()
    182                                         : false;
    183 
    184     if (needsStencil) {
    185         GrRenderTarget* rt = proxy->peekRenderTarget();
    186 
    187         if (!rt->renderTargetPriv().getStencilAttachment()) {
    188             return false;
    189         }
    190     }
    191 
    192     GrSurface* surface = proxy->peekSurface();
    193     if (surface->wasDestroyed()) {
    194         return false;
    195     }
    196 
    197     return true;
    198 }
    199 
    200 #ifdef SK_DEBUG
    201 static const char* op_to_name(GrLoadOp op) {
    202     return GrLoadOp::kLoad == op ? "load" : GrLoadOp::kClear == op ? "clear" : "discard";
    203 }
    204 
    205 void GrOpList::dump(bool printDependencies) const {
    206     SkDebugf("--------------------------------------------------------------\n");
    207     SkDebugf("opListID: %d - proxyID: %d - surfaceID: %d\n", fUniqueID,
    208              fTarget.get() ? fTarget.get()->uniqueID().asUInt() : -1,
    209              fTarget.get() && fTarget.get()->peekSurface()
    210                      ? fTarget.get()->peekSurface()->uniqueID().asUInt()
    211                      : -1);
    212     SkDebugf("ColorLoadOp: %s %x StencilLoadOp: %s\n",
    213              op_to_name(fColorLoadOp),
    214              GrLoadOp::kClear == fColorLoadOp ? fLoadClearColor.toBytes_RGBA() : 0x0,
    215              op_to_name(fStencilLoadOp));
    216 
    217     if (printDependencies) {
    218         SkDebugf("I rely On (%d): ", fDependencies.count());
    219         for (int i = 0; i < fDependencies.count(); ++i) {
    220             SkDebugf("%d, ", fDependencies[i]->fUniqueID);
    221         }
    222         SkDebugf("\n");
    223 
    224         SkDebugf("(%d) Rely On Me: ", fDependents.count());
    225         for (int i = 0; i < fDependents.count(); ++i) {
    226             SkDebugf("%d, ", fDependents[i]->fUniqueID);
    227         }
    228         SkDebugf("\n");
    229     }
    230 }
    231 #endif
    232