| /* | |
| * 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/task/ComputeTask.h" | |
| #include "include/private/SkAssert.h" | |
| #include "src/gpu/graphite/CommandBuffer.h" | |
| #include "src/gpu/graphite/ComputePipeline.h" // IWYU pragma: keep | |
| #include "src/gpu/graphite/Sampler.h" // IWYU pragma: keep | |
| #include "src/gpu/graphite/TextureProxy.h" // IWYU pragma: keep | |
| #include "src/gpu/graphite/compute/DispatchGroup.h" | |
| #include <cstddef> | |
| #include <utility> | |
| namespace skgpu::graphite { | |
| sk_sp<ComputeTask> ComputeTask::Make(DispatchGroupList dispatchGroups) { | |
| return sk_sp<ComputeTask>(new ComputeTask(std::move(dispatchGroups))); | |
| } | |
| ComputeTask::ComputeTask(DispatchGroupList dispatchGroups) | |
| : fDispatchGroups(std::move(dispatchGroups)), fChildTasks(fDispatchGroups.size()) { | |
| for (auto& group : fDispatchGroups) { | |
| fChildTasks.push_back(group->snapChildTask()); | |
| } | |
| } | |
| ComputeTask::~ComputeTask() = default; | |
| Task::Status ComputeTask::prepareResources(ResourceProvider* provider, | |
| ScratchResourceManager* scratchManager, | |
| sk_sp<const RuntimeEffectDictionary> rtd) { | |
| for (auto& child : fChildTasks) { | |
| if (child) { | |
| Status status = child->prepareResources(provider, scratchManager, rtd); | |
| if (status == Status::kFail) { | |
| return Status::kFail; | |
| } else if (status == Status::kDiscard) { | |
| child.reset(); | |
| } | |
| } | |
| } | |
| for (const auto& group : fDispatchGroups) { | |
| // TODO: Allow ComputeTasks to instantiate with scratch textures and return them. | |
| if (!group->prepareResources(provider)) { | |
| return Status::kFail; | |
| } | |
| } | |
| return Status::kSuccess; | |
| } | |
| Task::Status ComputeTask::addCommands(Context* ctx, | |
| CommandBuffer* commandBuffer, | |
| ReplayTargetData rtd) { | |
| if (fDispatchGroups.empty()) { | |
| return Status::kDiscard; | |
| } | |
| SkASSERT(fDispatchGroups.size() == fChildTasks.size()); | |
| const std::unique_ptr<DispatchGroup>* currentSpanPtr = &fDispatchGroups[0]; | |
| size_t currentSpanSize = 0u; | |
| for (int i = 0; i < fDispatchGroups.size(); ++i) { | |
| // If the next DispatchGroup has a dependent task, then encode the accumulated span as a | |
| // compute pass now. CommandBuffer encodes each compute pass with a separate encoder, so | |
| // the dependent task can use a non-compute encoder if needed. | |
| Task* child = fChildTasks[i].get(); | |
| if (child) { | |
| if (currentSpanSize > 0u) { | |
| if (!commandBuffer->addComputePass({currentSpanPtr, currentSpanSize})) { | |
| return Status::kFail; | |
| } | |
| currentSpanPtr = &fDispatchGroups[i]; | |
| currentSpanSize = 0u; | |
| } | |
| Status status = child->addCommands(ctx, commandBuffer, rtd); | |
| if (status == Status::kFail) { | |
| return Status::kFail; | |
| } else if (status == Status::kDiscard) { | |
| fChildTasks[i].reset(); | |
| } | |
| } | |
| currentSpanSize++; | |
| } | |
| return (currentSpanSize == 0u || | |
| commandBuffer->addComputePass({currentSpanPtr, currentSpanSize})) ? Status::kSuccess | |
| : Status::kFail; | |
| } | |
| } // namespace skgpu::graphite |