1 /*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "src/gpu/graphite/compute/ComputeStep.h"
9
10 #include "include/private/base/SkAssert.h"
11
12 #include <atomic>
13 #include <unordered_set>
14
15 namespace skgpu::graphite {
16 namespace {
17
next_id()18 static uint32_t next_id() {
19 static std::atomic<int32_t> nextId{0};
20 // Not worried about overflow since a Context isn't expected to have that many ComputeSteps.
21 // Even if this it wraps around to 0, that ComputeStep will not be in the same Context as the
22 // original 0.
23 return nextId.fetch_add(1, std::memory_order_relaxed);
24 }
25
26 } // namespace
27
ComputeStep(std::string_view name,WorkgroupSize localDispatchSize,SkSpan<const ResourceDesc> resources)28 ComputeStep::ComputeStep(std::string_view name,
29 WorkgroupSize localDispatchSize,
30 SkSpan<const ResourceDesc> resources)
31 : fUniqueID(next_id())
32 , fFlags(Flags::kNone)
33 , fName(name)
34 , fResources(resources.begin(), resources.end())
35 , fLocalDispatchSize(localDispatchSize) {
36 #ifdef SK_DEBUG
37 std::unordered_set<int> slots;
38 #endif
39 for (const ResourceDesc& r : fResources) {
40 #ifdef SK_DEBUG
41 // Validate that slot assignments within a ComputeStep are unique.
42 if (r.fFlow == DataFlow::kShared) {
43 SkASSERT(r.fSlot > -1);
44 SkASSERT(r.fSlot < kMaxComputeDataFlowSlots);
45 auto [_, inserted] = slots.insert(r.fSlot);
46 SkASSERT(inserted);
47 }
48 #endif // SK_DEBUG
49 switch (r.fFlow) {
50 case DataFlow::kVertexOutput:
51 SkASSERT(r.fType == ResourceType::kStorageBuffer);
52 SkASSERTF(!(fFlags & Flags::kOutputsVertexBuffer),
53 "a ComputeStep cannot produce more than one vertex buffer");
54 fFlags |= Flags::kOutputsVertexBuffer;
55 break;
56 case DataFlow::kIndexOutput:
57 SkASSERT(r.fType == ResourceType::kStorageBuffer);
58 SkASSERTF(!(fFlags & Flags::kOutputsIndexBuffer),
59 "a ComputeStep cannot produce more than one index buffer");
60 fFlags |= Flags::kOutputsIndexBuffer;
61 break;
62 case DataFlow::kInstanceOutput:
63 SkASSERT(r.fType == ResourceType::kStorageBuffer);
64 SkASSERTF(!(fFlags & Flags::kOutputsInstanceBuffer),
65 "a ComputeStep cannot produce more than one instance buffer");
66 fFlags |= Flags::kOutputsInstanceBuffer;
67 break;
68 case DataFlow::kIndirectDrawOutput:
69 // More than one indirect buffer output cannot be specified.
70 SkASSERTF(!(fFlags & Flags::kOutputsIndirectDrawBuffer),
71 "a ComputeStep cannot produce more than indirect buffer");
72 fFlags |= Flags::kOutputsIndirectDrawBuffer;
73 break;
74 default:
75 break;
76 }
77 }
78 }
79
prepareBuffer(const DrawParams &,int,int,const ResourceDesc &,void *,size_t) const80 void ComputeStep::prepareBuffer(
81 const DrawParams&, int, int, const ResourceDesc&, void*, size_t) const {
82 SK_ABORT("ComputeSteps using a mapped resource must override prepareBuffer()");
83 }
84
85 } // namespace skgpu::graphite
86