Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fe19203

Browse files
csmartdalton86Skia Commit-Bot
authored andcommitted
Initiate regeneration of mipmaps from proxy DAG land
This allows us to resolve all the textures before executing a command buffer, rather than interrupting execution as is currently done in the GL backend. Change-Id: I998546b312d24cf47fc2c837e7c94fbf95571af0 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/230636 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
1 parent 19db240 commit fe19203

15 files changed

Lines changed: 355 additions & 44 deletions

gn/gpu.gni

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ skia_gpu_sources = [
232232
"$_src/gpu/GrTextureRenderTargetProxy.cpp",
233233
"$_src/gpu/GrTextureRenderTargetProxy.h",
234234
"$_src/gpu/GrTextureResolveManager.h",
235+
"$_src/gpu/GrTextureResolveRenderTask.cpp",
236+
"$_src/gpu/GrTextureResolveRenderTask.h",
235237
"$_src/gpu/GrTRecorder.h",
236238
"$_src/gpu/GrUserStencilSettings.h",
237239
"$_src/gpu/GrWindowRectangles.h",

include/private/GrTypesPriv.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,17 @@ class GrRefCntedCallback : public SkRefCnt {
15701570
Context fReleaseCtx;
15711571
};
15721572

1573+
/**
1574+
* Indicates "resolutions" that need to be done on a texture before it can be sampled from.
1575+
*/
1576+
enum class GrTextureResolveFlags {
1577+
kNone = 0,
1578+
kMipMaps = 1 << 0, // Regenerate all mipmap levels.
1579+
// TODO: kMSAA = 1 << 1 // Blit the MSAA render buffer into a standard texture.
1580+
};
1581+
1582+
GR_MAKE_BITFIELD_CLASS_OPS(GrTextureResolveFlags)
1583+
15731584
#if GR_TEST_UTILS || defined(SK_ENABLE_DUMP_GPU)
15741585
static constexpr const char* GrBackendApiToStr(GrBackendApi api) {
15751586
switch (api) {

src/gpu/GrDrawingManager.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "src/gpu/GrTexturePriv.h"
3131
#include "src/gpu/GrTextureProxy.h"
3232
#include "src/gpu/GrTextureProxyPriv.h"
33+
#include "src/gpu/GrTextureResolveRenderTask.h"
3334
#include "src/gpu/GrTracing.h"
3435
#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
3536
#include "src/gpu/text/GrTextContext.h"
@@ -81,8 +82,16 @@ bool GrDrawingManager::RenderTaskDAG::isUsed(GrSurfaceProxy* proxy) const {
8182
return false;
8283
}
8384

84-
void GrDrawingManager::RenderTaskDAG::add(sk_sp<GrRenderTask> renderTask) {
85-
fRenderTasks.emplace_back(std::move(renderTask));
85+
GrRenderTask* GrDrawingManager::RenderTaskDAG::add(sk_sp<GrRenderTask> renderTask) {
86+
return fRenderTasks.emplace_back(std::move(renderTask)).get();
87+
}
88+
89+
GrRenderTask* GrDrawingManager::RenderTaskDAG::addBeforeLast(sk_sp<GrRenderTask> renderTask) {
90+
SkASSERT(!fRenderTasks.empty());
91+
// Release 'fRenderTasks.back()' and grab the raw pointer. If we pass in a reference to an array
92+
// element, and the array grows during emplace_back, then the reference will become invalidated.
93+
fRenderTasks.emplace_back(fRenderTasks.back().release());
94+
return (fRenderTasks[fRenderTasks.count() - 2] = std::move(renderTask)).get();
8695
}
8796

8897
void GrDrawingManager::RenderTaskDAG::add(const SkTArray<sk_sp<GrRenderTask>>& opLists) {
@@ -499,17 +508,18 @@ GrSemaphoresSubmitted GrDrawingManager::flushSurfaces(GrSurfaceProxy* proxies[],
499508
if (!proxies[i]->isInstantiated()) {
500509
return result;
501510
}
502-
}
503-
504-
for (int i = 0; i < numProxies; ++i) {
505511
GrSurface* surface = proxies[i]->peekSurface();
506512
if (auto* rt = surface->asRenderTarget()) {
507513
gpu->resolveRenderTarget(rt);
508514
}
509-
if (auto* tex = surface->asTexture()) {
510-
if (tex->texturePriv().mipMapped() == GrMipMapped::kYes &&
511-
tex->texturePriv().mipMapsAreDirty()) {
512-
gpu->regenerateMipMapLevels(tex);
515+
// If, after a flush, any of the proxies of interest have dirty mipmaps, regenerate them in
516+
// case their backend textures are being stolen.
517+
// (This special case is exercised by the ReimportImageTextureWithMipLevels test.)
518+
// FIXME: It may be more ideal to plumb down a "we're going to steal the backends" flag.
519+
if (auto* textureProxy = proxies[i]->asTextureProxy()) {
520+
if (textureProxy->mipMapsAreDirty()) {
521+
gpu->regenerateMipMapLevels(textureProxy->peekTexture());
522+
textureProxy->markMipMapsClean();
513523
}
514524
}
515525
}
@@ -669,6 +679,24 @@ sk_sp<GrTextureOpList> GrDrawingManager::newTextureOpList(sk_sp<GrTextureProxy>
669679
return opList;
670680
}
671681

682+
GrRenderTask* GrDrawingManager::newTextureResolveRenderTask(
683+
sk_sp<GrTextureProxy> textureProxy, GrTextureResolveFlags flags, const GrCaps& caps) {
684+
// Unlike in the "new opList" cases, we do not want to close the active opList, nor (if we are
685+
// in sorting and opList reduction mode) the render tasks that depend on the proxy's current
686+
// state. This is because those opLists can still receive new ops and because if they refer to
687+
// the mipmapped version of 'textureProxy', they will then come to depend on the render task
688+
// being created here.
689+
// NOTE: In either case, 'textureProxy' should already be closed at this point (i.e., its state
690+
// is finished))
691+
SkASSERT(!textureProxy->getLastRenderTask() || textureProxy->getLastRenderTask()->isClosed());
692+
auto textureResolveTask = GrTextureResolveRenderTask::Make(textureProxy, flags, caps);
693+
SkASSERT(textureProxy->getLastRenderTask() == textureResolveTask.get());
694+
// Add the new textureResolveTask before the fActiveOpList (if not in
695+
// sorting/opList-splitting-reduction mode) because it will depend upon this resolve task.
696+
// NOTE: Putting it here will also reduce the amount of work required by the topological sort.
697+
return fDAG.addBeforeLast(std::move(textureResolveTask));
698+
}
699+
672700
GrTextContext* GrDrawingManager::getTextContext() {
673701
if (!fTextContext) {
674702
fTextContext = GrTextContext::Make(fOptionsForTextContext);

src/gpu/GrDrawingManager.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ class GrDrawingManager {
5252
sk_sp<GrRenderTargetOpList> newRTOpList(sk_sp<GrRenderTargetProxy>, bool managedOpList);
5353
sk_sp<GrTextureOpList> newTextureOpList(sk_sp<GrTextureProxy>);
5454

55+
// Create a new, specialized, render task that will regenerate mipmap levels and/or resolve
56+
// MSAA (depending on GrTextureResolveFlags). This method will add the new render task to the
57+
// list of render tasks and make it depend on the target texture proxy. It is up to the caller
58+
// to add any dependencies on the new render task.
59+
GrRenderTask* newTextureResolveRenderTask(
60+
sk_sp<GrTextureProxy>, GrTextureResolveFlags, const GrCaps&);
61+
5562
GrRecordingContext* getContext() { return fContext; }
5663

5764
GrTextContext* getTextContext();
@@ -130,7 +137,8 @@ class GrDrawingManager {
130137
GrRenderTask* back() { return fRenderTasks.back().get(); }
131138
const GrRenderTask* back() const { return fRenderTasks.back().get(); }
132139

133-
void add(sk_sp<GrRenderTask>);
140+
GrRenderTask* add(sk_sp<GrRenderTask>);
141+
GrRenderTask* addBeforeLast(sk_sp<GrRenderTask>);
134142
void add(const SkTArray<sk_sp<GrRenderTask>>&);
135143

136144
void swap(SkTArray<sk_sp<GrRenderTask>>* renderTasks);

src/gpu/GrRenderTargetContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ class SK_API GrRenderTargetContext : public GrSurfaceContext {
502502
#if GR_TEST_UTILS
503503
bool testingOnly_IsInstantiated() const { return fRenderTargetProxy->isInstantiated(); }
504504
void testingOnly_SetPreserveOpsOnFullClear() { fPreserveOpsOnFullClear_TestingOnly = true; }
505+
GrRenderTargetOpList* testingOnly_PeekLastOpList() { return fOpList.get(); }
505506
#endif
506507

507508
protected:

src/gpu/GrRenderTargetOpList.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,12 @@ GrRenderTargetOpList::GrRenderTargetOpList(sk_sp<GrOpMemoryPool> opMemoryPool,
356356
: INHERITED(std::move(opMemoryPool), std::move(proxy), auditTrail)
357357
, fLastClipStackGenID(SK_InvalidUniqueID)
358358
SkDEBUGCODE(, fNumClips(0)) {
359+
if (GrTextureProxy* textureProxy = fTarget->asTextureProxy()) {
360+
if (GrMipMapped::kYes == textureProxy->mipMapped()) {
361+
textureProxy->markMipMapsDirty();
362+
}
363+
}
364+
fTarget->setLastRenderTask(this);
359365
}
360366

361367
void GrRenderTargetOpList::deleteOps() {

src/gpu/GrRenderTask.cpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ GrRenderTask::GrRenderTask(sk_sp<GrSurfaceProxy> target)
2424
: fTarget(std::move(target))
2525
, fUniqueID(CreateUniqueID())
2626
, fFlags(0) {
27-
fTarget->setLastRenderTask(this);
2827
}
2928

3029
GrRenderTask::~GrRenderTask() {
@@ -69,13 +68,44 @@ void GrRenderTask::addDependency(GrRenderTask* dependedOn) {
6968
}
7069

7170
// Convert from a GrSurface-based dependency to a GrRenderTask one
72-
void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped, GrTextureResolveManager,
71+
void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapped,
72+
GrTextureResolveManager textureResolveManager,
7373
const GrCaps& caps) {
74-
if (dependedOn->getLastRenderTask()) {
74+
GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask();
75+
76+
GrTextureProxy* textureProxy = dependedOn->asTextureProxy();
77+
SkASSERT(GrMipMapped::kNo == mipMapped || textureProxy);
78+
79+
// Does this proxy have mipmaps that need to be regenerated?
80+
if (GrMipMapped::kYes == mipMapped && textureProxy->mipMapsAreDirty()) {
81+
// We only read our own target during dst reads, and we shouldn't use mipmaps in that case.
82+
SkASSERT(dependedOnTask != this);
83+
84+
// Create an opList that resolves the texture's mipmap data.
85+
GrRenderTask* textureResolveTask = textureResolveManager.newTextureResolveRenderTask(
86+
sk_ref_sp(textureProxy), GrTextureResolveFlags::kMipMaps, caps);
87+
88+
// The GrTextureResolveRenderTask factory should have called addDependency (in this
89+
// instance, recursively) on the textureProxy.
90+
SkASSERT(!dependedOnTask || textureResolveTask->dependsOn(dependedOnTask));
91+
SkASSERT(!textureProxy->texPriv().isDeferred() ||
92+
textureResolveTask->fDeferredProxies.back() == textureProxy);
93+
94+
// The GrTextureResolveRenderTask factory should have also marked the mipmaps clean and set
95+
// the last opList on the textureProxy to textureResolveTask.
96+
SkASSERT(!textureProxy->mipMapsAreDirty());
97+
SkASSERT(textureProxy->getLastRenderTask() == textureResolveTask);
98+
99+
// Fall through and add textureResolveTask as a dependency of "this".
100+
dependedOnTask = textureResolveTask;
101+
} else if (textureProxy && textureProxy->texPriv().isDeferred()) {
102+
fDeferredProxies.push_back(textureProxy);
103+
}
104+
105+
if (dependedOnTask) {
75106
// If it is still receiving dependencies, this GrRenderTask shouldn't be closed
76107
SkASSERT(!this->isClosed());
77108

78-
GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask();
79109
if (dependedOnTask == this) {
80110
// self-read - presumably for dst reads. We can't make it closed in the self-read case.
81111
} else {
@@ -87,12 +117,6 @@ void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped, GrText
87117
dependedOnTask->makeClosed(caps);
88118
}
89119
}
90-
91-
if (GrTextureProxy* textureProxy = dependedOn->asTextureProxy()) {
92-
if (textureProxy->texPriv().isDeferred()) {
93-
fDeferredProxies.push_back(textureProxy);
94-
}
95-
}
96120
}
97121

98122
bool GrRenderTask::dependsOn(const GrRenderTask* dependedOn) const {

src/gpu/GrTextureOpList.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ GrTextureOpList::GrTextureOpList(sk_sp<GrOpMemoryPool> opMemoryPool,
2929
: INHERITED(std::move(opMemoryPool), proxy, auditTrail) {
3030
SkASSERT(fOpMemoryPool);
3131
SkASSERT(!proxy->readOnly());
32+
if (GrMipMapped::kYes == proxy->mipMapped()) {
33+
proxy->markMipMapsDirty();
34+
}
35+
fTarget->setLastRenderTask(this);
3236
}
3337

3438
void GrTextureOpList::deleteOp(int index) {

src/gpu/GrTextureProxy.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ class GrTextureProxy : virtual public GrSurfaceProxy {
4141
(GrMipMapsStatus::kNotAllocated == fMipMapsStatus));
4242
return GrMipMapped::kYes == fMipMapped && GrMipMapsStatus::kValid != fMipMapsStatus;
4343
}
44+
void markMipMapsDirty() {
45+
SkASSERT(GrMipMapped::kYes == fMipMapped);
46+
fMipMapsStatus = GrMipMapsStatus::kDirty;
47+
}
48+
void markMipMapsClean() {
49+
SkASSERT(GrMipMapped::kYes == fMipMapped);
50+
fMipMapsStatus = GrMipMapsStatus::kValid;
51+
}
4452

4553
// Returns the GrMipMapped value of the proxy from creation time regardless of whether it has
4654
// been instantiated or not.

src/gpu/GrTextureResolveManager.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#define GrTextureResolveManager_DEFINED
1010

1111
#include "include/core/SkRefCnt.h"
12-
#include "include/gpu/GrTypes.h"
12+
#include "src/gpu/GrDrawingManager.h"
1313

1414
class GrCaps;
1515
class GrDrawingManager;
@@ -26,19 +26,14 @@ class GrTextureResolveManager {
2626
explicit GrTextureResolveManager(GrDrawingManager* drawingManager)
2727
: fDrawingManager(drawingManager) {}
2828

29-
enum class ResolveFlags : bool {
30-
kNone = 0,
31-
kMipMaps = 1 << 0,
32-
// TODO: kMSAA = 1 << 1
33-
};
34-
3529
GrRenderTask* newTextureResolveRenderTask(
36-
sk_sp<GrTextureProxy>, ResolveFlags, const GrCaps&) const;
30+
sk_sp<GrTextureProxy> proxy, GrTextureResolveFlags flags, const GrCaps& caps) const {
31+
SkASSERT(fDrawingManager);
32+
return fDrawingManager->newTextureResolveRenderTask(std::move(proxy), flags, caps);
33+
}
3734

3835
private:
3936
GrDrawingManager* fDrawingManager;
4037
};
4138

42-
GR_MAKE_BITFIELD_CLASS_OPS(GrTextureResolveManager::ResolveFlags);
43-
4439
#endif

0 commit comments

Comments
 (0)