Remove RenderTarget pointer from GrRenderTargetOpList::RecordedOp

Change-Id: I08afe531cd9c65af4b3f6b6006bc3eaf7071cfec

Change-Id: I08afe531cd9c65af4b3f6b6006bc3eaf7071cfec
Reviewed-on: https://skia-review.googlesource.com/17117
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Robert Phillips 2017-05-17 09:36:38 -04:00 committed by Skia Commit-Bot
parent 292bf7a163
commit 318c419d3e
11 changed files with 53 additions and 132 deletions

View File

@ -81,9 +81,7 @@ public:
fCurrentStackTrace.push_back(SkString(framename));
}
void addOp(const GrOp*,
GrGpuResource::UniqueID resourceID,
GrRenderTargetProxy::UniqueID proxyID);
void addOp(const GrOp*, GrRenderTargetProxy::UniqueID proxyID);
void opsCombined(const GrOp* consumer, const GrOp* consumed);
@ -106,21 +104,12 @@ public:
// We could just return our internal bookkeeping struct if copying the data out becomes
// a performance issue, but until then its nice to decouple
struct OpInfo {
// Will the resourceID comparison yield the same decision as the proxyID comparison?
bool sameDecision(GrGpuResource::UniqueID resourceUniqueID,
GrSurfaceProxy::UniqueID proxyUniqueID) const {
return (fResourceUniqueID == resourceUniqueID) ==
(fProxyUniqueID == proxyUniqueID);
}
struct Op {
int fClientID;
SkRect fBounds;
};
SkRect fBounds;
// MDB TODO: remove fResourceUniqueID
GrGpuResource::UniqueID fResourceUniqueID;
GrSurfaceProxy::UniqueID fProxyUniqueID;
SkTArray<Op> fOps;
};
@ -148,15 +137,11 @@ private:
typedef SkTArray<Op*> Ops;
struct OpNode {
OpNode(const GrGpuResource::UniqueID& resourceID, const GrSurfaceProxy::UniqueID& proxyID)
: fResourceUniqueID(resourceID)
, fProxyUniqueID(proxyID) {
}
OpNode(const GrSurfaceProxy::UniqueID& proxyID) : fProxyUniqueID(proxyID) { }
SkString toJson() const;
SkRect fBounds;
Ops fChildren;
const GrGpuResource::UniqueID fResourceUniqueID;
const GrSurfaceProxy::UniqueID fProxyUniqueID;
};
typedef SkTArray<std::unique_ptr<OpNode>, true> OpList;
@ -189,8 +174,8 @@ private:
#define GR_AUDIT_TRAIL_RESET(audit_trail) \
//GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, fullReset);
#define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, resource_id, proxy_id) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addOp, op, resource_id, proxy_id);
#define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, proxy_id) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addOp, op, proxy_id);
#define GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(audit_trail, combineWith, op) \
GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, opsCombined, combineWith, op);

View File

@ -10,9 +10,7 @@
const int GrAuditTrail::kGrAuditTrailInvalidID = -1;
void GrAuditTrail::addOp(const GrOp* op,
GrGpuResource::UniqueID resourceID,
GrRenderTargetProxy::UniqueID proxyID) {
void GrAuditTrail::addOp(const GrOp* op, GrRenderTargetProxy::UniqueID proxyID) {
SkASSERT(fEnabled);
Op* auditOp = new Op;
fOpPool.emplace_back(auditOp);
@ -46,7 +44,7 @@ void GrAuditTrail::addOp(const GrOp* op,
// We use the op pointer as a key to find the OpNode we are 'glomming' ops onto
fIDLookup.set(op->uniqueID(), auditOp->fOpListID);
OpNode* opNode = new OpNode(resourceID, proxyID);
OpNode* opNode = new OpNode(proxyID);
opNode->fBounds = op->bounds();
opNode->fChildren.push_back(auditOp);
fOpList.emplace_back(opNode);
@ -91,7 +89,6 @@ void GrAuditTrail::copyOutFromOpList(OpInfo* outOpInfo, int opListID) {
const OpNode* bn = fOpList[opListID].get();
SkASSERT(bn);
outOpInfo->fBounds = bn->fBounds;
outOpInfo->fResourceUniqueID = bn->fResourceUniqueID;
outOpInfo->fProxyUniqueID = bn->fProxyUniqueID;
for (int j = 0; j < bn->fChildren.count(); j++) {
OpInfo::Op& outOp = outOpInfo->fOps.push_back();
@ -289,7 +286,6 @@ SkString GrAuditTrail::Op::toJson() const {
SkString GrAuditTrail::OpNode::toJson() const {
SkString json;
json.append("{");
json.appendf("\"ResourceID\": \"%u\",", fResourceUniqueID.asUInt());
json.appendf("\"ProxyID\": \"%u\",", fProxyUniqueID.asUInt());
skrect_to_json(&json, "Bounds", fBounds);
JsonifyTArray(&json, "Ops", fChildren, true);

View File

@ -93,7 +93,6 @@ void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType
// but need to be flushed anyway. Closing such GrOpLists here will mean new
// GrOpLists will be created to replace them if the SkGpuDevice(s) write to them again.
fOpLists[i]->makeClosed(*fContext->caps());
SkDEBUGCODE(fOpLists[i]->validateTargetsSingleRenderTarget());
}
#ifdef ENABLE_MDB
@ -127,7 +126,6 @@ void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType
continue; // Odd - but not a big deal
}
opList->makeClosed(*fContext->caps());
SkDEBUGCODE(opList->validateTargetsSingleRenderTarget());
opList->prepareOps(&fFlushState);
if (!opList->executeOps(&fFlushState)) {
continue; // This is bad
@ -137,10 +135,6 @@ void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType
}
}
for (int i = 0; i < fOpLists.count(); ++i) {
fOpLists[i]->prepareOps(&fFlushState);
}
#if 0
// Enable this to print out verbose GrOp information
for (int i = 0; i < fOpLists.count(); ++i) {
@ -148,10 +142,23 @@ void GrDrawingManager::internalFlush(GrSurfaceProxy*, GrResourceCache::FlushType
}
#endif
for (int i = 0; i < fOpLists.count(); ++i) {
if (!fOpLists[i]->instantiate(fContext->resourceProvider())) {
fOpLists[i] = nullptr;
continue;
}
fOpLists[i]->prepareOps(&fFlushState);
}
// Upload all data to the GPU
fFlushState.preIssueDraws();
for (int i = 0; i < fOpLists.count(); ++i) {
if (!fOpLists[i]) {
continue;
}
if (fOpLists[i]->executeOps(&fFlushState)) {
flushed = true;
}

View File

@ -34,6 +34,10 @@ GrOpList::~GrOpList() {
}
}
bool GrOpList::instantiate(GrResourceProvider* resourceProvider) {
return SkToBool(fTarget.get()->instantiate(resourceProvider));
}
void GrOpList::reset() {
if (fTarget.get() && this == fTarget.get()->getLastOpList()) {
fTarget.get()->setLastOpList(nullptr);

View File

@ -19,6 +19,7 @@ class GrAuditTrail;
class GrCaps;
class GrOpFlushState;
class GrRenderTargetOpList;
class GrResourceProvider;
class GrSurfaceProxy;
class GrTextureOpList;
@ -27,7 +28,8 @@ public:
GrOpList(GrSurfaceProxy*, GrAuditTrail*);
~GrOpList() override;
// These two methods are invoked as flush time
// These three methods are invoked at flush time
bool instantiate(GrResourceProvider* resourceProvider);
virtual void prepareOps(GrOpFlushState* flushState) = 0;
virtual bool executeOps(GrOpFlushState* flushState) = 0;
@ -73,8 +75,6 @@ public:
*/
SkDEBUGCODE(virtual void dump() const;)
SkDEBUGCODE(virtual void validateTargetsSingleRenderTarget() const = 0;)
SkDEBUGCODE(virtual int numOps() const = 0;)
SkDEBUGCODE(virtual int numClips() const { return 0; })

View File

@ -60,37 +60,21 @@ void GrRenderTargetOpList::dump() const {
}
}
}
void GrRenderTargetOpList::validateTargetsSingleRenderTarget() const {
GrRenderTarget* rt = nullptr;
for (int i = 0; i < fRecordedOps.count(); ++i) {
if (!fRecordedOps[i].fOp) {
continue; // combined forward
}
if (!rt) {
rt = fRecordedOps[i].fRenderTarget.get();
} else {
SkASSERT(fRecordedOps[i].fRenderTarget.get() == rt);
}
}
}
#endif
void GrRenderTargetOpList::prepareOps(GrOpFlushState* flushState) {
SkASSERT(fTarget.get()->priv().peekRenderTarget());
SkASSERT(this->isClosed());
// Loop over the ops that haven't yet been prepared.
for (int i = 0; i < fRecordedOps.count(); ++i) {
if (fRecordedOps[i].fOp) {
GrOpFlushState::DrawOpArgs opArgs;
if (fRecordedOps[i].fRenderTarget) {
opArgs = {
fRecordedOps[i].fRenderTarget.get(),
fRecordedOps[i].fAppliedClip,
fRecordedOps[i].fDstTexture
};
}
GrOpFlushState::DrawOpArgs opArgs = {
fTarget.get()->priv().peekRenderTarget(),
fRecordedOps[i].fAppliedClip,
fRecordedOps[i].fDstTexture
};
flushState->setDrawOpArgs(&opArgs);
fRecordedOps[i].fOp->prepare(flushState);
flushState->setDrawOpArgs(nullptr);
@ -132,14 +116,7 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) {
return false;
}
#ifdef SK_DEBUG
GrSurface* target = fTarget.get()->instantiate(flushState->resourceProvider());
if (!target) {
return false;
}
const GrRenderTarget* currentRenderTarget = target->asRenderTarget();
SkASSERT(currentRenderTarget);
#endif
SkASSERT(fTarget.get()->priv().peekRenderTarget());
std::unique_ptr<GrGpuCommandBuffer> commandBuffer = create_command_buffer(flushState->gpu());
flushState->setCommandBuffer(commandBuffer.get());
@ -150,8 +127,6 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) {
continue;
}
SkASSERT(fRecordedOps[i].fRenderTarget.get() == currentRenderTarget);
if (fRecordedOps[i].fOp->needsCommandBufferIsolation()) {
// This op is a special snowflake and must occur between command buffers
// TODO: make this go through the command buffer
@ -165,7 +140,7 @@ bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) {
}
GrOpFlushState::DrawOpArgs opArgs {
fRecordedOps[i].fRenderTarget.get(),
fTarget.get()->priv().peekRenderTarget(),
fRecordedOps[i].fAppliedClip,
fRecordedOps[i].fDstTexture
};
@ -299,21 +274,9 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
GrRenderTargetContext* renderTargetContext,
GrAppliedClip* clip,
const DstTexture* dstTexture) {
GrRenderTarget* renderTarget = renderTargetContext->accessRenderTarget();
if (!renderTarget) {
SkASSERT(false);
return nullptr;
}
SkASSERT(fTarget.get());
const GrCaps* caps = renderTargetContext->caps();
#ifdef SK_DEBUG
if (!fRecordedOps.empty()) {
GrRenderTargetOpList::RecordedOp& back = fRecordedOps.back();
SkASSERT(back.fRenderTarget == renderTarget);
}
#endif
// A closed GrOpList should never receive new/more ops
SkASSERT(!this->isClosed());
@ -321,7 +284,7 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
// 1) check every op
// 2) intersect with something
// 3) find a 'blocker'
GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), renderTarget->uniqueID(),
GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(),
renderTargetContext->asRenderTargetProxy()->uniqueID());
GrOP_INFO("opList: %d Recording (%s, opID: %u)\n"
"\tBounds [L: %.2f, T: %.2f R: %.2f B: %.2f]\n",
@ -334,17 +297,11 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
GrOP_INFO("\tOutcome:\n");
int maxCandidates = SkTMin(kMaxOpLookback, fRecordedOps.count());
// If we don't have a valid destination render target then we cannot reorder.
if (maxCandidates && renderTarget) {
if (maxCandidates) {
int i = 0;
while (true) {
const RecordedOp& candidate = fRecordedOps.fromBack(i);
// We cannot continue to search backwards if the render target changes
if (candidate.fRenderTarget.get() != renderTarget) {
GrOP_INFO("\t\tBackward: Breaking because of (%s, opID: %u) Rendertarget mismatch\n",
candidate.fOp->name(),
candidate.fOp->uniqueID());
break;
}
if (this->combineIfPossible(candidate, op.get(), clip, dstTexture, *caps)) {
GrOP_INFO("\t\tBackward: Combining with (%s, opID: %u)\n", candidate.fOp->name(),
candidate.fOp->uniqueID());
@ -373,7 +330,7 @@ GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
clip = fClipAllocator.make<GrAppliedClip>(std::move(*clip));
SkDEBUGCODE(fNumClips++;)
}
fRecordedOps.emplace_back(std::move(op), renderTarget, clip, dstTexture);
fRecordedOps.emplace_back(std::move(op), clip, dstTexture);
fRecordedOps.back().fOp->wasRecorded(this);
fLastFullClearOp = nullptr;
fLastFullClearResourceID.makeInvalid();
@ -386,23 +343,12 @@ void GrRenderTargetOpList::forwardCombine(const GrCaps& caps) {
for (int i = 0; i < fRecordedOps.count() - 1; ++i) {
GrOp* op = fRecordedOps[i].fOp.get();
GrRenderTarget* renderTarget = fRecordedOps[i].fRenderTarget.get();
SkASSERT(renderTarget);
// If we don't have a valid destination render target ID then we cannot reorder.
if (!renderTarget) {
continue;
}
int maxCandidateIdx = SkTMin(i + kMaxOpLookahead, fRecordedOps.count() - 1);
int j = i + 1;
while (true) {
const RecordedOp& candidate = fRecordedOps[j];
// We cannot continue to search if the render target changes
if (candidate.fRenderTarget.get() != renderTarget) {
GrOP_INFO("\t\tForward: Breaking because of (%s, opID: %u) Rendertarget\n",
candidate.fOp->name(),
candidate.fOp->uniqueID());
break;
}
if (this->combineIfPossible(fRecordedOps[i], candidate.fOp.get(),
candidate.fAppliedClip, &candidate.fDstTexture, caps)) {
GrOP_INFO("\t\tForward: Combining with (%s, opID: %u)\n", candidate.fOp->name(),

View File

@ -104,8 +104,6 @@ public:
SkDEBUGCODE(void dump() const override;)
SkDEBUGCODE(void validateTargetsSingleRenderTarget() const override;)
SkDEBUGCODE(int numOps() const override { return fRecordedOps.count(); })
SkDEBUGCODE(int numClips() const override { return fNumClips; })
@ -114,19 +112,15 @@ private:
struct RecordedOp {
RecordedOp(std::unique_ptr<GrOp> op,
GrRenderTarget* rt,
const GrAppliedClip* appliedClip,
const DstTexture* dstTexture)
: fOp(std::move(op))
, fRenderTarget(rt)
, fAppliedClip(appliedClip) {
if (dstTexture) {
fDstTexture = *dstTexture;
}
}
std::unique_ptr<GrOp> fOp;
// TODO: These ops will all to target the same render target and this won't be needed.
GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> fRenderTarget;
DstTexture fDstTexture;
const GrAppliedClip* fAppliedClip;
};

View File

@ -21,6 +21,10 @@ public:
return fProxy->fTarget ? fProxy->fTarget->asTexture() : nullptr;
}
GrRenderTarget* peekRenderTarget() const {
return fProxy->fTarget ? fProxy->fTarget->asRenderTarget() : nullptr;
}
// Beware! This call is only guaranteed to tell you if the proxy in question has
// any pending IO in its current state. It won't tell you about the IO state in the
// future when the proxy is actually used/instantiated.

View File

@ -41,10 +41,6 @@ void GrTextureOpList::dump() const {
}
}
void GrTextureOpList::validateTargetsSingleRenderTarget() const {
SkASSERT(1 == fRecordedOps.count() || 0 == fRecordedOps.count());
}
#endif
void GrTextureOpList::prepareOps(GrOpFlushState* flushState) {
@ -93,20 +89,16 @@ bool GrTextureOpList::copySurface(GrResourceProvider* resourceProvider,
this->addDependency(src);
#endif
// See the comment in GrRenderTargetOpList about why we pass the invalid ID here.
this->recordOp(std::move(op),
GrGpuResource::UniqueID::InvalidID(),
GrSurfaceProxy::UniqueID::InvalidID());
this->recordOp(std::move(op));
return true;
}
void GrTextureOpList::recordOp(std::unique_ptr<GrOp> op,
GrGpuResource::UniqueID resourceUniqueID,
GrSurfaceProxy::UniqueID proxyUniqueID) {
void GrTextureOpList::recordOp(std::unique_ptr<GrOp> op) {
SkASSERT(fTarget.get());
// A closed GrOpList should never receive new/more ops
SkASSERT(!this->isClosed());
GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), resourceUniqueID, proxyUniqueID);
GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), fTarget.get()->uniqueID());
GrOP_INFO("Re-Recording (%s, opID: %u)\n"
"\tBounds LRTB (%f, %f, %f, %f)\n",
op->name(),

View File

@ -62,16 +62,10 @@ public:
SkDEBUGCODE(void dump() const override;)
SkDEBUGCODE(virtual void validateTargetsSingleRenderTarget() const override;)
SkDEBUGCODE(int numOps() const override { return fRecordedOps.count(); })
private:
// MDB TODO: The unique IDs are only needed for the audit trail. There should only be one
// on the opList itself.
void recordOp(std::unique_ptr<GrOp>,
GrGpuResource::UniqueID resourceUniqueID,
GrSurfaceProxy::UniqueID proxyUniqueID);
void recordOp(std::unique_ptr<GrOp>);
SkSTArray<2, std::unique_ptr<GrOp>, true> fRecordedOps;

View File

@ -287,7 +287,7 @@ void SkDebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
// drawn offscreen
GrRenderTargetContext* rtc =
originalCanvas->internal_private_accessTopLayerRenderTargetContext();
GrGpuResource::UniqueID rtID = rtc->accessRenderTarget()->uniqueID();
GrSurfaceProxy::UniqueID proxyID = rtc->asSurfaceProxy()->uniqueID();
// get the bounding boxes to draw
SkTArray<GrAuditTrail::OpInfo> childrenBounds;
@ -301,8 +301,7 @@ void SkDebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(1);
for (int i = 0; i < childrenBounds.count(); i++) {
SkASSERT(childrenBounds[i].sameDecision(rtID, rtc->asSurfaceProxy()->uniqueID()));
if (childrenBounds[i].fResourceUniqueID != rtID) {
if (childrenBounds[i].fProxyUniqueID != proxyID) {
// offscreen draw, ignore for now
continue;
}