blob: 8078aa1d8f7058036f066321b16aff828138df47 [file] [log] [blame]
/*
* Copyright 2023 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/compute/ComputeStep.h"
#include "include/private/base/SkAssert.h"
#include <atomic>
#include <unordered_set>
namespace skgpu::graphite {
namespace {
static uint32_t next_id() {
static std::atomic<int32_t> nextId{0};
// Not worried about overflow since a Context isn't expected to have that many ComputeSteps.
// Even if this it wraps around to 0, that ComputeStep will not be in the same Context as the
// original 0.
return nextId.fetch_add(1, std::memory_order_relaxed);
}
} // namespace
ComputeStep::ComputeStep(std::string_view name,
WorkgroupSize localDispatchSize,
SkSpan<const ResourceDesc> resources)
: fUniqueID(next_id())
, fFlags(Flags::kNone)
, fName(name)
, fResources(resources.begin(), resources.end())
, fLocalDispatchSize(localDispatchSize) {
#ifdef SK_DEBUG
std::unordered_set<int> slots;
#endif
for (const ResourceDesc& r : fResources) {
#ifdef SK_DEBUG
// Validate that slot assignments within a ComputeStep are unique.
if (r.fFlow == DataFlow::kShared) {
SkASSERT(r.fSlot > -1);
SkASSERT(r.fSlot < kMaxComputeDataFlowSlots);
auto [_, inserted] = slots.insert(r.fSlot);
SkASSERT(inserted);
}
#endif // SK_DEBUG
switch (r.fFlow) {
case DataFlow::kVertexOutput:
SkASSERT(r.fType == ResourceType::kStorageBuffer);
SkASSERTF(!(fFlags & Flags::kOutputsVertexBuffer),
"a ComputeStep cannot produce more than one vertex buffer");
fFlags |= Flags::kOutputsVertexBuffer;
break;
case DataFlow::kIndexOutput:
SkASSERT(r.fType == ResourceType::kStorageBuffer);
SkASSERTF(!(fFlags & Flags::kOutputsIndexBuffer),
"a ComputeStep cannot produce more than one index buffer");
fFlags |= Flags::kOutputsIndexBuffer;
break;
case DataFlow::kInstanceOutput:
SkASSERT(r.fType == ResourceType::kStorageBuffer);
SkASSERTF(!(fFlags & Flags::kOutputsInstanceBuffer),
"a ComputeStep cannot produce more than one instance buffer");
fFlags |= Flags::kOutputsInstanceBuffer;
break;
case DataFlow::kIndirectDrawOutput:
// More than one indirect buffer output cannot be specified.
SkASSERTF(!(fFlags & Flags::kOutputsIndirectDrawBuffer),
"a ComputeStep cannot produce more than indirect buffer");
fFlags |= Flags::kOutputsIndirectDrawBuffer;
break;
default:
break;
}
}
}
void ComputeStep::prepareBuffer(
const DrawParams&, int, int, const ResourceDesc&, void*, size_t) const {
SK_ABORT("ComputeSteps using a mapped resource must override prepareBuffer()");
}
} // namespace skgpu::graphite