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

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

Powered by Google App Engine
This is Rietveld 408576698