Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Side by Side Diff: gpu/command_buffer/client/client_discardable_manager.cc

Issue 2814583002: Service/ClientDiscardableManager (Closed)
Patch Set: rename Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/client/client_discardable_manager.h"
6
7 #include "base/memory/ptr_util.h"
8 #include "base/sys_info.h"
9
10 namespace gpu {
11 namespace {
12
13 // Stores a set of offsets, initially 0 to |element_count_|. Allows callers to
14 // take and return offsets from the set. Internally stores the offsets as a set
15 // of ranges. This means that in the worst case (every other offset taken), the
16 // set will use |element_count_| uints, but should typically use fewer.
17 class FreeOffsetSet {
18 public:
19 // Creates a new set, containing 0 to |element_count|.
20 FreeOffsetSet(uint32_t element_count);
piman 2017/05/08 20:20:27 nit: explicit
ericrk 2017/05/10 21:36:02 Done.
21
22 // Returns true if the set contains at least one element.
23 bool HasFreeOffset() const;
24
25 // Returns true if any element from the set has been taken.
26 bool HasUsedOffset() const;
27
28 // Takes a free offset from the set. Should only be called if HasFreeOffset().
29 uint32_t TakeFreeOffset();
30
31 // Returns an offset to the set.
32 void ReturnFreeOffset(uint32_t offset);
33
34 private:
35 struct FreeRange {
36 uint32_t start;
37 uint32_t end;
38 };
39 struct CompareFreeRanges {
40 bool operator()(const FreeRange& a, const FreeRange& b) const {
41 return a.start < b.start;
42 }
43 };
44
45 const uint32_t element_count_;
46 std::set<FreeRange, CompareFreeRanges> free_ranges_;
piman 2017/05/08 20:20:27 nit: base::flat_set? For 4k pages, we'll always ha
ericrk 2017/05/10 21:36:02 Makes sense - will give this a try.
47
48 DISALLOW_COPY_AND_ASSIGN(FreeOffsetSet);
49 };
50
51 FreeOffsetSet::FreeOffsetSet(uint32_t element_count)
52 : element_count_(element_count) {
53 free_ranges_.insert({0, element_count_});
54 }
55
56 bool FreeOffsetSet::HasFreeOffset() const {
57 return !free_ranges_.empty();
58 }
59
60 bool FreeOffsetSet::HasUsedOffset() const {
61 if (free_ranges_.size() != 1 || free_ranges_.begin()->start != 0 ||
62 free_ranges_.begin()->end != element_count_)
63 return true;
64
65 return false;
66 }
67
68 uint32_t FreeOffsetSet::TakeFreeOffset() {
69 DCHECK(HasFreeOffset());
70
71 auto it = free_ranges_.begin();
72 uint32_t offset_to_return = it->start;
73
74 FreeRange new_range{it->start + 1, it->end};
75 free_ranges_.erase(it);
76 if (new_range.start != new_range.end)
77 free_ranges_.insert(new_range);
78
79 return offset_to_return;
80 }
81
82 void FreeOffsetSet::ReturnFreeOffset(uint32_t offset) {
83 FreeRange new_range{offset, offset + 1};
84
85 // Find the FreeRange directly before/after our new range.
86 auto next_range = free_ranges_.lower_bound(new_range);
87 auto prev_range = free_ranges_.end();
88 if (next_range != free_ranges_.begin()) {
89 prev_range = std::prev(next_range);
90 }
91
92 // Collapse ranges if possible.
93 if (next_range != free_ranges_.end() && next_range->start == new_range.end) {
94 new_range.end = next_range->end;
95 free_ranges_.erase(next_range);
96 }
97
98 if (prev_range != free_ranges_.end() && prev_range->end == new_range.start) {
99 new_range.start = prev_range->start;
100 free_ranges_.erase(prev_range);
101 }
102
103 free_ranges_.insert(new_range);
104 }
105
106 // Returns the size of the allocation which ClientDiscardableManager will
107 // sub-allocate from. This should be at least as big as the minimum shared
108 // memory allocation size.
109 size_t AllocationSize() {
110 size_t allocation_size = base::SysInfo::VMAllocationGranularity();
111 // If the allocation is small (less than 2K), round it up to at least 4K.
112 allocation_size = std::max(static_cast<size_t>(2048), allocation_size);
113 return allocation_size;
114 }
115
116 } // namespace
117
118 struct ClientDiscardableManager::Allocation {
119 Allocation(uint32_t element_count) : free_offsets(element_count) {}
120
121 scoped_refptr<Buffer> buffer;
122 int32_t shm_id = 0;
123 FreeOffsetSet free_offsets;
124 };
125
126 ClientDiscardableManager::ClientDiscardableManager()
127 : allocation_size_(AllocationSize()) {}
128 ClientDiscardableManager::~ClientDiscardableManager() = default;
129
130 ClientDiscardableHandle ClientDiscardableManager::InitializeTexture(
131 CommandBuffer* command_buffer,
132 uint32_t texture_id) {
133 DCHECK(texture_handles_.find(texture_id) == texture_handles_.end());
134
135 scoped_refptr<Buffer> buffer;
136 uint32_t offset = 0;
137 int32_t shm_id = 0;
138 FindAllocation(command_buffer, &buffer, &shm_id, &offset);
139 uint32_t byte_offset = offset * element_size_;
140 ClientDiscardableHandle handle(std::move(buffer), byte_offset, shm_id);
141 texture_handles_.emplace(texture_id, handle);
142 return handle;
143 }
144
145 bool ClientDiscardableManager::LockTexture(uint32_t texture_id) {
146 auto found = texture_handles_.find(texture_id);
147 DCHECK(found != texture_handles_.end());
148 return found->second.Lock();
149 }
150
151 void ClientDiscardableManager::FreeTexture(uint32_t texture_id) {
152 auto found = texture_handles_.find(texture_id);
153 if (found == texture_handles_.end())
154 return;
155 pending_handles_.push(found->second);
156 texture_handles_.erase(found);
157 }
158
159 bool ClientDiscardableManager::TextureIsValid(uint32_t texture_id) const {
160 return texture_handles_.find(texture_id) != texture_handles_.end();
161 }
162
163 void ClientDiscardableManager::FindAllocation(CommandBuffer* command_buffer,
164 scoped_refptr<Buffer>* buffer,
165 int32_t* shm_id,
166 uint32_t* offset) {
167 CheckPending(command_buffer);
piman 2017/05/02 22:21:03 The logic for this seems very similar to MappedMem
ericrk 2017/05/08 01:03:50 Good point. One thing which is a bit tricky is ens
piman 2017/05/08 20:20:27 Ok, fair enough. We have a bit of logic in e.g. St
168
169 for (auto& allocation : allocations_) {
170 if (!allocation->free_offsets.HasFreeOffset())
171 continue;
172
173 *offset = allocation->free_offsets.TakeFreeOffset();
174 *shm_id = allocation->shm_id;
175 *buffer = allocation->buffer;
176 return;
177 }
178
179 // We couldn't find an existing free entry. Allocate more space.
180 auto allocation = base::MakeUnique<Allocation>(elements_per_allocation_);
181 allocation->buffer = command_buffer->CreateTransferBuffer(
182 allocation_size_, &allocation->shm_id);
183
184 *offset = allocation->free_offsets.TakeFreeOffset();
185 *shm_id = allocation->shm_id;
186 *buffer = allocation->buffer;
187 allocations_.push_back(std::move(allocation));
188 }
189
190 void ClientDiscardableManager::ReturnAllocation(
191 CommandBuffer* command_buffer,
192 const ClientDiscardableHandle& handle) {
193 for (auto it = allocations_.begin(); it != allocations_.end(); ++it) {
194 Allocation* allocation = it->get();
195 if (allocation->shm_id != handle.shm_id())
196 continue;
197
198 allocation->free_offsets.ReturnFreeOffset(handle.byte_offset() /
199 element_size_);
200
201 if (!allocation->free_offsets.HasUsedOffset()) {
202 command_buffer->DestroyTransferBuffer(allocation->shm_id);
203 allocations_.erase(it);
204 return;
205 }
206 }
207 }
208
209 void ClientDiscardableManager::CheckPending(CommandBuffer* command_buffer) {
210 while (pending_handles_.size() > 0 &&
211 pending_handles_.front().CanBeReUsed()) {
212 ReturnAllocation(command_buffer, pending_handles_.front());
213 pending_handles_.pop();
214 }
215 }
216
217 ClientDiscardableHandle ClientDiscardableManager::GetHandleForTesting(
218 uint32_t texture_id) {
219 auto found = texture_handles_.find(texture_id);
220 DCHECK(found != texture_handles_.end());
221 return found->second;
222 }
223
224 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698