blob: b456eb7931d13ad49a4a2d481301310f30ffc569 [file] [log] [blame]
/*
* Copyright 2024 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/graphite/task/DrawTask.h"
#include "src/gpu/graphite/ScratchResourceManager.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureProxy.h"
namespace skgpu::graphite {
DrawTask::DrawTask(sk_sp<TextureProxy> target) : fTarget(std::move(target)) {}
DrawTask::~DrawTask() = default;
Task::Status DrawTask::prepareResources(ResourceProvider* resourceProvider,
ScratchResourceManager* scratchManager,
const RuntimeEffectDictionary* rteDict) {
const int pendingReadCount = scratchManager->pendingReadCount(fTarget.get());
if (pendingReadCount) {
// This DrawTask defines the content of a scratch device that has incremented the pending
// read count before snap() was called. The target may have already been instantiated if
// we've processed this task's children before.
SkASSERT(!fTarget->isLazy());
// Even though we may discard the task, we always want to mark it as in-use to track the
// pending reads to know when to return the texture.;
scratchManager->markResourceInUse(this);
if (fPrepared) {
// If the task has already had prepareResources() called once, it should have had
// its target instantiated.
SkASSERT(fTarget->isInstantiated());
// Return kDiscard so that this reference to the task is removed and the original
// encounter in the graph will be the only time addCommands() is invoked.
return Status::kDiscard;
}
} else {
// A non-scratch DrawTask should only ever be in the task graph one time.
SkASSERT(!fPrepared);
}
fPrepared = true;
// NOTE: This prepareResources() pushes a new scope for scratch resource management, which is
// what we want since the child tasks are what will actually instantiate any scratch device and
// trigger returns of any grand-child resources. The above markResourceInUse() should happen
// above this so that pending returns are handled in caller's scope.
return fChildTasks.prepareResources(resourceProvider, scratchManager, rteDict);
}
void DrawTask::onUseCompleted(ScratchResourceManager* scratchManager) {
// Now that the render task has completed, actually decrement the read count of the target proxy
// If the count hits zero, this was the last pending read that needed to use the DrawTask's
// results so we can return the texture to the ScratchResourceManager for reuse.
SkASSERT(!fTarget->isLazy() && fTarget->isInstantiated());
SkASSERT(scratchManager->pendingReadCount(fTarget.get()) > 0);
if (scratchManager->removePendingRead(fTarget.get())) {
scratchManager->returnTexture(fTarget->refTexture());
}
}
Task::Status DrawTask::addCommands(Context* ctx,
CommandBuffer* commandBuffer,
ReplayTargetData replayTarget) {
SkASSERT(fTarget->isInstantiated());
return fChildTasks.addCommands(ctx, commandBuffer, replayTarget);
}
} // namespace skgpu::graphite