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

Side by Side Diff: gpu/ipc/host/shader_disk_cache.cc

Issue 2565243002: Revert of gpu: Move ShaderDiskCache into //gpu/ipc/host component. (Closed)
Patch Set: Created 4 years 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
« no previous file with comments | « gpu/ipc/host/shader_disk_cache.h ('k') | gpu/ipc/host/shader_disk_cache_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 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/ipc/host/shader_disk_cache.h"
6
7 #include "base/macros.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/threading/thread_checker.h"
11 #include "gpu/command_buffer/common/constants.h"
12 #include "net/base/cache_type.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
15
16 namespace gpu {
17
18 namespace {
19
20 static const base::FilePath::CharType kGpuCachePath[] =
21 FILE_PATH_LITERAL("GPUCache");
22
23 static ShaderCacheFactory* factory_instance = nullptr;
24
25 } // namespace
26
27 // ShaderDiskCacheEntry handles the work of caching/updating the cached
28 // shaders.
29 class ShaderDiskCacheEntry : public base::ThreadChecker {
30 public:
31 ShaderDiskCacheEntry(ShaderDiskCache* cache,
32 const std::string& key,
33 const std::string& shader);
34 ~ShaderDiskCacheEntry();
35
36 void Cache();
37
38 private:
39 enum OpType {
40 OPEN_ENTRY,
41 WRITE_DATA,
42 CREATE_ENTRY,
43 };
44
45 void OnOpComplete(int rv);
46
47 int OpenCallback(int rv);
48 int WriteCallback(int rv);
49 int IOComplete(int rv);
50
51 ShaderDiskCache* cache_;
52 OpType op_type_;
53 std::string key_;
54 std::string shader_;
55 disk_cache::Entry* entry_;
56 base::WeakPtr<ShaderDiskCacheEntry> weak_ptr_;
57 base::WeakPtrFactory<ShaderDiskCacheEntry> weak_ptr_factory_;
58
59 DISALLOW_COPY_AND_ASSIGN(ShaderDiskCacheEntry);
60 };
61
62 // ShaderDiskReadHelper is used to load all of the cached shaders from the
63 // disk cache and send to the memory cache.
64 class ShaderDiskReadHelper : public base::ThreadChecker {
65 public:
66 using ShaderLoadedCallback = ShaderDiskCache::ShaderLoadedCallback;
67 ShaderDiskReadHelper(ShaderDiskCache* cache,
68 const ShaderLoadedCallback& callback);
69 ~ShaderDiskReadHelper();
70
71 void LoadCache();
72
73 private:
74 enum OpType {
75 TERMINATE,
76 OPEN_NEXT,
77 OPEN_NEXT_COMPLETE,
78 READ_COMPLETE,
79 ITERATION_FINISHED
80 };
81
82 void OnOpComplete(int rv);
83
84 int OpenNextEntry();
85 int OpenNextEntryComplete(int rv);
86 int ReadComplete(int rv);
87 int IterationComplete(int rv);
88
89 ShaderDiskCache* cache_;
90 ShaderLoadedCallback shader_loaded_callback_;
91 OpType op_type_;
92 std::unique_ptr<disk_cache::Backend::Iterator> iter_;
93 scoped_refptr<net::IOBufferWithSize> buf_;
94 disk_cache::Entry* entry_;
95 base::WeakPtrFactory<ShaderDiskReadHelper> weak_ptr_factory_;
96
97 DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper);
98 };
99
100 class ShaderClearHelper : public base::ThreadChecker {
101 public:
102 ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
103 const base::FilePath& path,
104 const base::Time& delete_begin,
105 const base::Time& delete_end,
106 const base::Closure& callback);
107 ~ShaderClearHelper();
108
109 void Clear();
110
111 private:
112 enum OpType { TERMINATE, VERIFY_CACHE_SETUP, DELETE_CACHE };
113
114 void DoClearShaderCache(int rv);
115
116 scoped_refptr<ShaderDiskCache> cache_;
117 OpType op_type_;
118 base::FilePath path_;
119 base::Time delete_begin_;
120 base::Time delete_end_;
121 base::Closure callback_;
122 base::WeakPtrFactory<ShaderClearHelper> weak_ptr_factory_;
123
124 DISALLOW_COPY_AND_ASSIGN(ShaderClearHelper);
125 };
126
127 ////////////////////////////////////////////////////////////////////////////////
128 // ShaderDiskCacheEntry
129
130 ShaderDiskCacheEntry::ShaderDiskCacheEntry(ShaderDiskCache* cache,
131 const std::string& key,
132 const std::string& shader)
133 : cache_(cache),
134 op_type_(OPEN_ENTRY),
135 key_(key),
136 shader_(shader),
137 entry_(nullptr),
138 weak_ptr_factory_(this) {
139 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
140 }
141
142 ShaderDiskCacheEntry::~ShaderDiskCacheEntry() {
143 DCHECK(CalledOnValidThread());
144 if (entry_)
145 entry_->Close();
146 }
147
148 void ShaderDiskCacheEntry::Cache() {
149 DCHECK(CalledOnValidThread());
150 int rv = cache_->backend()->OpenEntry(
151 key_, &entry_, base::Bind(&ShaderDiskCacheEntry::OnOpComplete,
152 weak_ptr_factory_.GetWeakPtr()));
153 if (rv != net::ERR_IO_PENDING)
154 OnOpComplete(rv);
155 }
156
157 void ShaderDiskCacheEntry::OnOpComplete(int rv) {
158 DCHECK(CalledOnValidThread());
159 // The function calls inside the switch block below can end up destroying
160 // |this|. So hold on to a WeakPtr<>, and terminate the while loop if |this|
161 // has been destroyed.
162 auto weak_ptr = std::move(weak_ptr_);
163 do {
164 switch (op_type_) {
165 case OPEN_ENTRY:
166 rv = OpenCallback(rv);
167 break;
168 case CREATE_ENTRY:
169 rv = WriteCallback(rv);
170 break;
171 case WRITE_DATA:
172 rv = IOComplete(rv);
173 break;
174 }
175 } while (rv != net::ERR_IO_PENDING && weak_ptr);
176 if (weak_ptr)
177 weak_ptr_ = std::move(weak_ptr);
178 }
179
180 int ShaderDiskCacheEntry::OpenCallback(int rv) {
181 DCHECK(CalledOnValidThread());
182 if (rv == net::OK) {
183 cache_->backend()->OnExternalCacheHit(key_);
184 cache_->EntryComplete(this);
185 return rv;
186 }
187
188 op_type_ = CREATE_ENTRY;
189 return cache_->backend()->CreateEntry(
190 key_, &entry_, base::Bind(&ShaderDiskCacheEntry::OnOpComplete,
191 weak_ptr_factory_.GetWeakPtr()));
192 }
193
194 int ShaderDiskCacheEntry::WriteCallback(int rv) {
195 DCHECK(CalledOnValidThread());
196 if (rv != net::OK) {
197 LOG(ERROR) << "Failed to create shader cache entry: " << rv;
198 cache_->EntryComplete(this);
199 return rv;
200 }
201
202 op_type_ = WRITE_DATA;
203 scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(shader_);
204 return entry_->WriteData(1, 0, io_buf.get(), shader_.length(),
205 base::Bind(&ShaderDiskCacheEntry::OnOpComplete,
206 weak_ptr_factory_.GetWeakPtr()),
207 false);
208 }
209
210 int ShaderDiskCacheEntry::IOComplete(int rv) {
211 DCHECK(CalledOnValidThread());
212 cache_->EntryComplete(this);
213 return rv;
214 }
215
216 ////////////////////////////////////////////////////////////////////////////////
217 // ShaderDiskReadHelper
218
219 ShaderDiskReadHelper::ShaderDiskReadHelper(ShaderDiskCache* cache,
220 const ShaderLoadedCallback& callback)
221 : cache_(cache),
222 shader_loaded_callback_(callback),
223 op_type_(OPEN_NEXT),
224 buf_(NULL),
225 entry_(NULL),
226 weak_ptr_factory_(this) {}
227
228 ShaderDiskReadHelper::~ShaderDiskReadHelper() {
229 DCHECK(CalledOnValidThread());
230 if (entry_)
231 entry_->Close();
232 iter_ = nullptr;
233 }
234
235 void ShaderDiskReadHelper::LoadCache() {
236 DCHECK(CalledOnValidThread());
237 OnOpComplete(net::OK);
238 }
239
240 void ShaderDiskReadHelper::OnOpComplete(int rv) {
241 DCHECK(CalledOnValidThread());
242 do {
243 switch (op_type_) {
244 case OPEN_NEXT:
245 rv = OpenNextEntry();
246 break;
247 case OPEN_NEXT_COMPLETE:
248 rv = OpenNextEntryComplete(rv);
249 break;
250 case READ_COMPLETE:
251 rv = ReadComplete(rv);
252 break;
253 case ITERATION_FINISHED:
254 rv = IterationComplete(rv);
255 break;
256 case TERMINATE:
257 cache_->ReadComplete();
258 rv = net::ERR_IO_PENDING; // break the loop
259 break;
260 }
261 } while (rv != net::ERR_IO_PENDING);
262 }
263
264 int ShaderDiskReadHelper::OpenNextEntry() {
265 DCHECK(CalledOnValidThread());
266 op_type_ = OPEN_NEXT_COMPLETE;
267 if (!iter_)
268 iter_ = cache_->backend()->CreateIterator();
269 return iter_->OpenNextEntry(&entry_,
270 base::Bind(&ShaderDiskReadHelper::OnOpComplete,
271 weak_ptr_factory_.GetWeakPtr()));
272 }
273
274 int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) {
275 DCHECK(CalledOnValidThread());
276 if (rv == net::ERR_FAILED) {
277 iter_.reset();
278 op_type_ = ITERATION_FINISHED;
279 return net::OK;
280 }
281
282 if (rv < 0)
283 return rv;
284
285 op_type_ = READ_COMPLETE;
286 buf_ = new net::IOBufferWithSize(entry_->GetDataSize(1));
287 return entry_->ReadData(1, 0, buf_.get(), buf_->size(),
288 base::Bind(&ShaderDiskReadHelper::OnOpComplete,
289 weak_ptr_factory_.GetWeakPtr()));
290 }
291
292 int ShaderDiskReadHelper::ReadComplete(int rv) {
293 DCHECK(CalledOnValidThread());
294 if (rv && rv == buf_->size() && !shader_loaded_callback_.is_null()) {
295 shader_loaded_callback_.Run(entry_->GetKey(),
296 std::string(buf_->data(), buf_->size()));
297 }
298
299 buf_ = NULL;
300 entry_->Close();
301 entry_ = NULL;
302
303 op_type_ = OPEN_NEXT;
304 return net::OK;
305 }
306
307 int ShaderDiskReadHelper::IterationComplete(int rv) {
308 DCHECK(CalledOnValidThread());
309 iter_.reset();
310 op_type_ = TERMINATE;
311 return net::OK;
312 }
313
314 ////////////////////////////////////////////////////////////////////////////////
315 // ShaderClearHelper
316
317 ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
318 const base::FilePath& path,
319 const base::Time& delete_begin,
320 const base::Time& delete_end,
321 const base::Closure& callback)
322 : cache_(std::move(cache)),
323 op_type_(VERIFY_CACHE_SETUP),
324 path_(path),
325 delete_begin_(delete_begin),
326 delete_end_(delete_end),
327 callback_(callback),
328 weak_ptr_factory_(this) {}
329
330 ShaderClearHelper::~ShaderClearHelper() {
331 DCHECK(CalledOnValidThread());
332 }
333
334 void ShaderClearHelper::Clear() {
335 DCHECK(CalledOnValidThread());
336 DoClearShaderCache(net::OK);
337 }
338
339 void ShaderClearHelper::DoClearShaderCache(int rv) {
340 DCHECK(CalledOnValidThread());
341 while (rv != net::ERR_IO_PENDING) {
342 switch (op_type_) {
343 case VERIFY_CACHE_SETUP:
344 rv = cache_->SetAvailableCallback(
345 base::Bind(&ShaderClearHelper::DoClearShaderCache,
346 weak_ptr_factory_.GetWeakPtr()));
347 op_type_ = DELETE_CACHE;
348 break;
349 case DELETE_CACHE:
350 rv = cache_->Clear(delete_begin_, delete_end_,
351 base::Bind(&ShaderClearHelper::DoClearShaderCache,
352 weak_ptr_factory_.GetWeakPtr()));
353 op_type_ = TERMINATE;
354 break;
355 case TERMINATE:
356 callback_.Run();
357 // Calling CacheCleared() destroys |this|.
358 ShaderCacheFactory::GetInstance()->CacheCleared(path_);
359 rv = net::ERR_IO_PENDING; // Break the loop.
360 break;
361 }
362 }
363 }
364
365 ////////////////////////////////////////////////////////////////////////////////
366 // ShaderCacheFactory
367
368 // static
369 void ShaderCacheFactory::InitInstance(
370 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
371 scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
372 if (task_runner->BelongsToCurrentThread()) {
373 CreateFactoryInstance(std::move(cache_task_runner));
374 } else {
375 task_runner->PostTask(FROM_HERE,
376 base::Bind(&ShaderCacheFactory::CreateFactoryInstance,
377 std::move(cache_task_runner)));
378 }
379 }
380
381 // static
382 ShaderCacheFactory* ShaderCacheFactory::GetInstance() {
383 DCHECK(!factory_instance || factory_instance->CalledOnValidThread());
384 return factory_instance;
385 }
386
387 ShaderCacheFactory::ShaderCacheFactory(
388 scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner)
389 : cache_task_runner_(std::move(cache_task_runner)) {}
390
391 ShaderCacheFactory::~ShaderCacheFactory() {}
392
393 // static
394 void ShaderCacheFactory::CreateFactoryInstance(
395 scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
396 DCHECK(!factory_instance);
397 factory_instance = new ShaderCacheFactory(std::move(cache_task_runner));
398 }
399
400 void ShaderCacheFactory::SetCacheInfo(int32_t client_id,
401 const base::FilePath& path) {
402 DCHECK(CalledOnValidThread());
403 client_id_to_path_map_[client_id] = path;
404 }
405
406 void ShaderCacheFactory::RemoveCacheInfo(int32_t client_id) {
407 DCHECK(CalledOnValidThread());
408 client_id_to_path_map_.erase(client_id);
409 }
410
411 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32_t client_id) {
412 DCHECK(CalledOnValidThread());
413 ClientIdToPathMap::iterator iter = client_id_to_path_map_.find(client_id);
414 if (iter == client_id_to_path_map_.end())
415 return NULL;
416 return ShaderCacheFactory::GetByPath(iter->second);
417 }
418
419 scoped_refptr<ShaderDiskCache> ShaderCacheFactory::GetByPath(
420 const base::FilePath& path) {
421 DCHECK(CalledOnValidThread());
422 ShaderCacheMap::iterator iter = shader_cache_map_.find(path);
423 if (iter != shader_cache_map_.end())
424 return iter->second;
425
426 ShaderDiskCache* cache = new ShaderDiskCache(path);
427 cache->Init(cache_task_runner_);
428 return cache;
429 }
430
431 void ShaderCacheFactory::AddToCache(const base::FilePath& key,
432 ShaderDiskCache* cache) {
433 DCHECK(CalledOnValidThread());
434 shader_cache_map_[key] = cache;
435 }
436
437 void ShaderCacheFactory::RemoveFromCache(const base::FilePath& key) {
438 DCHECK(CalledOnValidThread());
439 shader_cache_map_.erase(key);
440 }
441
442 void ShaderCacheFactory::ClearByPath(const base::FilePath& path,
443 const base::Time& delete_begin,
444 const base::Time& delete_end,
445 const base::Closure& callback) {
446 DCHECK(CalledOnValidThread());
447 DCHECK(!callback.is_null());
448
449 auto helper = base::MakeUnique<ShaderClearHelper>(
450 GetByPath(path), path, delete_begin, delete_end, callback);
451
452 // We could receive requests to clear the same path with different
453 // begin/end times. So, we keep a list of requests. If we haven't seen this
454 // path before we kick off the clear and add it to the list. If we have see it
455 // already, then we already have a clear running. We add this clear to the
456 // list and wait for any previous clears to finish.
457 ShaderClearMap::iterator iter = shader_clear_map_.find(path);
458 if (iter != shader_clear_map_.end()) {
459 iter->second.push(std::move(helper));
460 return;
461 }
462
463 // Insert the helper in the map before calling Clear(), since it can lead to a
464 // call back into CacheCleared().
465 ShaderClearHelper* helper_ptr = helper.get();
466 shader_clear_map_.insert(
467 std::pair<base::FilePath, ShaderClearQueue>(path, ShaderClearQueue()));
468 shader_clear_map_[path].push(std::move(helper));
469 helper_ptr->Clear();
470 }
471
472 void ShaderCacheFactory::CacheCleared(const base::FilePath& path) {
473 DCHECK(CalledOnValidThread());
474
475 ShaderClearMap::iterator iter = shader_clear_map_.find(path);
476 if (iter == shader_clear_map_.end()) {
477 LOG(ERROR) << "Completed clear but missing clear helper.";
478 return;
479 }
480
481 iter->second.pop();
482
483 // If there are remaining items in the list we trigger the Clear on the
484 // next one.
485 if (!iter->second.empty()) {
486 iter->second.front()->Clear();
487 return;
488 }
489
490 shader_clear_map_.erase(iter);
491 }
492
493 ////////////////////////////////////////////////////////////////////////////////
494 // ShaderDiskCache
495
496 ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path)
497 : cache_available_(false), cache_path_(cache_path), is_initialized_(false) {
498 ShaderCacheFactory::GetInstance()->AddToCache(cache_path_, this);
499 }
500
501 ShaderDiskCache::~ShaderDiskCache() {
502 ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_);
503 }
504
505 void ShaderDiskCache::Init(
506 scoped_refptr<base::SingleThreadTaskRunner> cache_task_runner) {
507 if (is_initialized_) {
508 NOTREACHED(); // can't initialize disk cache twice.
509 return;
510 }
511 is_initialized_ = true;
512
513 int rv = disk_cache::CreateCacheBackend(
514 net::SHADER_CACHE, net::CACHE_BACKEND_DEFAULT,
515 cache_path_.Append(kGpuCachePath),
516 gpu::kDefaultMaxProgramCacheMemoryBytes, true, cache_task_runner, NULL,
517 &backend_, base::Bind(&ShaderDiskCache::CacheCreatedCallback, this));
518
519 if (rv == net::OK)
520 cache_available_ = true;
521 }
522
523 void ShaderDiskCache::Cache(const std::string& key, const std::string& shader) {
524 if (!cache_available_)
525 return;
526
527 auto shim = base::MakeUnique<ShaderDiskCacheEntry>(this, key, shader);
528 shim->Cache();
529 auto* raw_ptr = shim.get();
530 entries_.insert(std::make_pair(raw_ptr, std::move(shim)));
531 }
532
533 int ShaderDiskCache::Clear(const base::Time begin_time,
534 const base::Time end_time,
535 const net::CompletionCallback& completion_callback) {
536 int rv;
537 if (begin_time.is_null()) {
538 rv = backend_->DoomAllEntries(completion_callback);
539 } else {
540 rv =
541 backend_->DoomEntriesBetween(begin_time, end_time, completion_callback);
542 }
543 return rv;
544 }
545
546 int32_t ShaderDiskCache::Size() {
547 if (!cache_available_)
548 return -1;
549 return backend_->GetEntryCount();
550 }
551
552 int ShaderDiskCache::SetAvailableCallback(
553 const net::CompletionCallback& callback) {
554 if (cache_available_)
555 return net::OK;
556 available_callback_ = callback;
557 return net::ERR_IO_PENDING;
558 }
559
560 void ShaderDiskCache::CacheCreatedCallback(int rv) {
561 if (rv != net::OK) {
562 LOG(ERROR) << "Shader Cache Creation failed: " << rv;
563 return;
564 }
565 helper_ =
566 base::MakeUnique<ShaderDiskReadHelper>(this, shader_loaded_callback_);
567 helper_->LoadCache();
568 }
569
570 void ShaderDiskCache::EntryComplete(ShaderDiskCacheEntry* entry) {
571 entries_.erase(entry);
572 if (entries_.empty() && !cache_complete_callback_.is_null())
573 cache_complete_callback_.Run(net::OK);
574 }
575
576 void ShaderDiskCache::ReadComplete() {
577 helper_ = nullptr;
578
579 // The cache is considered available after we have finished reading any
580 // of the old cache values off disk. This prevents a potential race where we
581 // are reading from disk and execute a cache clear at the same time.
582 cache_available_ = true;
583 if (!available_callback_.is_null()) {
584 available_callback_.Run(net::OK);
585 available_callback_.Reset();
586 }
587 }
588
589 int ShaderDiskCache::SetCacheCompleteCallback(
590 const net::CompletionCallback& callback) {
591 if (entries_.empty()) {
592 return net::OK;
593 }
594 cache_complete_callback_ = callback;
595 return net::ERR_IO_PENDING;
596 }
597
598 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/ipc/host/shader_disk_cache.h ('k') | gpu/ipc/host/shader_disk_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698