blob: 6488be59e5b0c66fe13cf724973af9290491da99 [file]
/*
* Copyright 2022 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/GpuWorkSubmission.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/graphite/Buffer.h"
#include "src/gpu/graphite/CommandBuffer.h"
#include "src/gpu/graphite/QueueManager.h"
namespace skgpu::graphite {
GpuWorkSubmission::GpuWorkSubmission(std::unique_ptr<CommandBuffer> cmdBuffer,
QueueManager* queueManager)
: GpuWorkSubmission(std::move(cmdBuffer), /*protectedCmdBuffer=*/nullptr, queueManager) {}
GpuWorkSubmission::GpuWorkSubmission(std::unique_ptr<CommandBuffer> cmdBuffer,
std::unique_ptr<CommandBuffer> protectedCmdBuffer,
QueueManager* queueManager)
: fCommandBuffer(std::move(cmdBuffer))
, fProtectedCommandBuffer(std::move(protectedCmdBuffer))
, fQueueManager(queueManager) {
// Protected command buffers cannot write to unprotected host-accessible memory,
// so they will never have buffers to async map.
SkASSERT(!fProtectedCommandBuffer ||
fProtectedCommandBuffer->buffersToAsyncMapOnSubmit().empty());
if (fCommandBuffer) {
SkSpan<const sk_sp<Buffer>> buffers = fCommandBuffer->buffersToAsyncMapOnSubmit();
if (!buffers.empty()) {
fOutstandingAsyncMapCounter = sk_make_sp<SkRefCnt>();
for (auto& buffer : buffers) {
SkASSERT(!buffer->isUnmappable());
fOutstandingAsyncMapCounter->ref();
buffer->asyncMap([](GpuFinishedContext c, CallbackResult) {
static_cast<SkRefCnt*>(c)->unref();
}, fOutstandingAsyncMapCounter.get());
}
}
}
}
GpuWorkSubmission::~GpuWorkSubmission() {
auto cleanup = [this](std::unique_ptr<CommandBuffer>& commandBuffer) {
if (commandBuffer) {
commandBuffer->resetCommandBuffer();
fQueueManager->returnCommandBuffer(std::move(commandBuffer));
}
};
this->callFinishedProcs(/*success=*/true);
cleanup(fCommandBuffer);
cleanup(fProtectedCommandBuffer);
}
bool GpuWorkSubmission::isFinished(const SharedContext* sharedContext) {
return this->onIsFinished(sharedContext) &&
(!fOutstandingAsyncMapCounter || fOutstandingAsyncMapCounter->unique());
}
void GpuWorkSubmission::waitUntilFinished(const SharedContext* sharedContext) {
this->onWaitUntilFinished(sharedContext);
if (fOutstandingAsyncMapCounter) {
while (!fOutstandingAsyncMapCounter->unique()) {
fQueueManager->tick();
}
}
}
void GpuWorkSubmission::addFinishedProc(sk_sp<RefCntedCallback> finishedProc) {
if (finishedProc) {
fFinishedProcs.push_back(std::move(finishedProc));
}
}
void GpuWorkSubmission::addFinishedProcs(
skia_private::TArray<sk_sp<RefCntedCallback>> finishedProcs) {
for (int i = 0; i < finishedProcs.size(); ++i) {
if (finishedProcs[i]) {
fFinishedProcs.push_back(std::move(finishedProcs[i]));
}
}
}
std::optional<GpuStats> GpuWorkSubmission::gpuStats() const {
std::optional<GpuStats> unprotectedStats =
fCommandBuffer ? fCommandBuffer->gpuStats() : std::nullopt;
std::optional<GpuStats> protectedStats =
fProtectedCommandBuffer ? fProtectedCommandBuffer->gpuStats() : std::nullopt;
if (unprotectedStats && protectedStats) {
GpuStats stats;
stats.elapsedTime = unprotectedStats->elapsedTime + protectedStats->elapsedTime;
stats.numOcclusionPassSamples
= unprotectedStats->numOcclusionPassSamples + protectedStats->numOcclusionPassSamples;
return stats;
} else if (unprotectedStats) {
return unprotectedStats;
} else {
return protectedStats;
}
}
void GpuWorkSubmission::callFinishedProcs(bool success) {
if (!success) {
for (int i = 0; i < fFinishedProcs.size(); ++i) {
fFinishedProcs[i]->setFailureResult();
}
} else {
if (auto stats = this->gpuStats()) {
for (int i = 0; i < fFinishedProcs.size(); ++i) {
if (fFinishedProcs[i]->receivesGpuStats()) {
fFinishedProcs[i]->setStats(*stats);
}
}
}
}
fFinishedProcs.clear();
}
} // namespace skgpu::graphite