Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Resource.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 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
9
12
13namespace skgpu::graphite {
14
15namespace {
16uint32_t create_unique_id() {
17 static std::atomic<uint32_t> nextID{1};
18 uint32_t id;
19 do {
20 id = nextID.fetch_add(1, std::memory_order_relaxed);
21 } while (id == SK_InvalidUniqueID);
22 return id;
23}
24} // namespace anonymous
25
26Resource::Resource(const SharedContext* sharedContext,
27 Ownership ownership,
28 skgpu::Budgeted budgeted,
29 size_t gpuMemorySize,
30 std::string_view label,
31 bool commandBufferRefsAsUsageRefs)
32 : fSharedContext(sharedContext)
33 , fUsageRefCnt(1)
34 , fCommandBufferRefCnt(0)
35 , fCacheRefCnt(0)
36 , fCommandBufferRefsAsUsageRefs(commandBufferRefsAsUsageRefs)
37 , fOwnership(ownership)
38 , fGpuMemorySize(gpuMemorySize)
39 , fBudgeted(budgeted)
40 , fUniqueID(create_unique_id()) {
41 // If we don't own the resource that must mean its wrapped in a client object. Thus we should
42 // not be budgeted
43 SkASSERT(fOwnership == Ownership::kOwned || fBudgeted == skgpu::Budgeted::kNo);
44
45 this->setLabel(label);
46}
47
49 // The cache should have released or destroyed this resource.
50 SkASSERT(this->wasDestroyed());
51}
52
53void Resource::registerWithCache(sk_sp<ResourceCache> returnCache) {
54 SkASSERT(!fReturnCache);
55 SkASSERT(returnCache);
56
57 fReturnCache = std::move(returnCache);
58}
59
60bool Resource::notifyARefIsZero(LastRemovedRef removedRef) const {
61 // No resource should have been destroyed if there was still any sort of ref on it.
62 SkASSERT(!this->wasDestroyed());
63
64 Resource* mutableThis = const_cast<Resource*>(this);
65
66 // TODO: We have not switched all resources to use the ResourceCache yet. Once we do we should
67 // be able to assert that we have an fCacheReturn.
68 // SkASSERT(fReturnCache);
69 if (removedRef != LastRemovedRef::kCache &&
70 fReturnCache &&
71 fReturnCache->returnResource(mutableThis, removedRef)) {
72 return false;
73 }
74
75 if (!this->hasAnyRefs()) {
76 return true;
77 }
78 return false;
79}
80
81void Resource::internalDispose() {
82 SkASSERT(fSharedContext);
83 this->invokeReleaseProc();
84 this->freeGpuData();
85 fSharedContext = nullptr;
86 // TODO: If we ever support freeing all the backend objects without deleting the object, we'll
87 // need to add a hasAnyRefs() check here.
88 delete this;
89}
90
91bool Resource::isPurgeable() const {
92 // For being purgeable we don't care if there are cacheRefs on the object since the cacheRef
93 // will always be greater than 1 since we add one on insert and don't remove that ref until
94 // the Resource is removed from the cache.
95 return !(this->hasUsageRef() || this->hasCommandBufferRef());
96}
97
99 if (this->ownership() == Ownership::kWrapped && !traceMemoryDump->shouldDumpWrappedObjects()) {
100 return;
101 }
102
103 if (this->budgeted() == skgpu::Budgeted::kNo &&
104 !traceMemoryDump->shouldDumpUnbudgetedObjects()) {
105 return;
106 }
107
108 size_t size = this->gpuMemorySize();
109
110 // Avoid dumping objects without a size (e.g. Samplers, pipelines, etc).
111 // TODO: Would a client ever actually want to see all of this? Wouldn't be hard to add it as an
112 // option.
113 if (size == 0) {
114 return;
115 }
116
117 SkString resourceName("skia/gpu_resources/resource_");
118 resourceName.appendU32(this->uniqueID().asUInt());
119
120 traceMemoryDump->dumpNumericValue(resourceName.c_str(), "size", "bytes", size);
121 traceMemoryDump->dumpStringValue(resourceName.c_str(), "type", this->getResourceType());
122 traceMemoryDump->dumpStringValue(resourceName.c_str(), "label", this->getLabel().c_str());
123 if (this->isPurgeable()) {
124 traceMemoryDump->dumpNumericValue(resourceName.c_str(), "purgeable_size", "bytes", size);
125 }
126 if (traceMemoryDump->shouldDumpWrappedObjects()) {
127 traceMemoryDump->dumpWrappedState(resourceName.c_str(),
128 this->ownership() == Ownership::kWrapped);
129 }
130 if (traceMemoryDump->shouldDumpUnbudgetedObjects()) {
131 traceMemoryDump->dumpBudgetedState(resourceName.c_str(),
132 this->budgeted() == skgpu::Budgeted::kYes);
133 }
134
135 this->onDumpMemoryStatistics(traceMemoryDump, resourceName.c_str());
136
137 // TODO: implement this to report real gpu id backing the resource. Will be virtual implemented
138 // by backend specific resource subclasses.
139 //this->setMemoryBacking(traceMemoryDump, resourceName);
140}
141
142} // namespace skgpu::graphite
143
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr uint32_t SK_InvalidUniqueID
Definition SkTypes.h:196
void appendU32(uint32_t value)
Definition SkString.h:210
const char * c_str() const
Definition SkString.h:133
virtual bool shouldDumpUnbudgetedObjects() const
virtual void dumpWrappedState(const char *, bool)
virtual void dumpStringValue(const char *, const char *, const char *)
virtual void dumpBudgetedState(const char *, bool)
virtual bool shouldDumpWrappedObjects() const
virtual void dumpNumericValue(const char *dumpName, const char *valueName, const char *units, uint64_t value)=0
bool wasDestroyed() const
Definition Resource.h:151
skgpu::Budgeted budgeted() const
Definition Resource.h:100
virtual void invokeReleaseProc()
Definition Resource.h:193
Resource(const Resource &)=delete
virtual void onDumpMemoryStatistics(SkTraceMemoryDump *traceMemoryDump, const char *dumpName) const
Definition Resource.h:196
size_t gpuMemorySize() const
Definition Resource.h:104
UniqueID uniqueID() const
Definition Resource.h:123
void setLabel(std::string_view label)
Definition Resource.h:136
Ownership ownership() const
Definition Resource.h:98
virtual void freeGpuData()=0
void dumpMemoryStatistics(SkTraceMemoryDump *traceMemoryDump) const
Definition Resource.cpp:98
Budgeted
Definition GpuTypes.h:35
const uintptr_t id