summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h
blob: 2bdfbc2d76b88f029392f6a6a46d3a77e1e1f929 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_RESOURCE_PROVIDER_CACHE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_RESOURCE_PROVIDER_CACHE_H_

#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "gpu/command_buffer/client/webgpu_interface.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"

namespace blink {

class WebGPURecyclableResourceCache;

struct ResourceCacheKey {
  ResourceCacheKey(const IntSize& size,
                   const CanvasResourceParams& params,
                   bool is_origin_top_left);
  ~ResourceCacheKey() = default;
  bool operator==(const ResourceCacheKey& other) const;
  bool operator!=(const ResourceCacheKey& other) const;

  // If we support more parameters for CreateWebGPUImageProvider(), we should
  // add them here.
  const IntSize size;
  const CanvasResourceParams params;
  const bool is_origin_top_left;
};

class PLATFORM_EXPORT RecyclableCanvasResource {
 public:
  explicit RecyclableCanvasResource(
      std::unique_ptr<CanvasResourceProvider> resource_provider,
      const ResourceCacheKey& cache_key,
      base::WeakPtr<WebGPURecyclableResourceCache> cache);

  ~RecyclableCanvasResource();

  CanvasResourceProvider* resource_provider() {
    return resource_provider_.get();
  }

 private:
  std::unique_ptr<CanvasResourceProvider> resource_provider_;
  const ResourceCacheKey cache_key_;
  base::WeakPtr<WebGPURecyclableResourceCache> cache_;
};

class PLATFORM_EXPORT WebGPURecyclableResourceCache {
 public:
  explicit WebGPURecyclableResourceCache(
      base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  ~WebGPURecyclableResourceCache() = default;

  std::unique_ptr<RecyclableCanvasResource> GetOrCreateCanvasResource(
      const IntSize& size,
      const CanvasResourceParams& params,
      bool is_origin_top_left);

  // When the holder is destroyed, move the resource provider to
  // |unused_providers_| if the cache is not full.
  void OnDestroyRecyclableResource(
      std::unique_ptr<CanvasResourceProvider> resource_provider);

  wtf_size_t CleanUpResourcesAndReturnSizeForTesting();

  int GetWaitCountBeforeDeletionForTesting() {
    return kTimerIdDeltaForDeletion;
  }

 private:
  // The maximum number of unused CanvasResourceProviders size, 128 MB.
  static constexpr int kMaxRecyclableResourceCachesInKB = 128 * 1024;
  static constexpr int kMaxRecyclableResourceCachesInBytes =
      kMaxRecyclableResourceCachesInKB * 1024;

  // A resource is deleted from the cache if it's not reused after this delay.
  static constexpr int kCleanUpDelayInSeconds = 2;

  // The duration set to the resource clean-up timer function.
  // Because the resource clean-up function runs every kCleanUpDelayInSeconds
  // and the stale resource can only be deleted in the call to
  // ReleaseStaleResources(). The actually delay could be as long as
  // (kCleanUpDelayInSeconds + kCleanUpDelayInSeconds).
  static constexpr int kTimerDurationInSeconds = 1;

  // The time it takes to increase the Timer Id by this delta is equivalent to
  // kCleanUpDelayInSeconds.
  static constexpr int kTimerIdDeltaForDeletion =
      kCleanUpDelayInSeconds / kTimerDurationInSeconds;

  struct Resource {
    explicit Resource(std::unique_ptr<CanvasResourceProvider> resource_provider,
                      unsigned int timer_id,
                      int resource_size)
        : resource_provider_(std::move(resource_provider)),
          timer_id_(timer_id),
          resource_size_(resource_size) {}

    std::unique_ptr<CanvasResourceProvider> resource_provider_;
    unsigned int timer_id_ = 0;
    int resource_size_ = 0;
  };

  using DequeResourceProvider = WTF::Deque<Resource>;

  // Search |unused_providers_| and acquire the canvas resource provider with
  // the same cache key for re-use.
  std::unique_ptr<CanvasResourceProvider> AcquireCachedProvider(
      const ResourceCacheKey& cache_key);

  // Release the stale resources which are recycled before the last clean-up.
  void ReleaseStaleResources();

  // Start the clean-up function runs when there are unused resources.
  void StartResourceCleanUpTimer();

  // This is the place to keep the unused CanvasResourceProviders. They are
  // waiting to be used. MRU is in the front of the deque.
  DequeResourceProvider unused_providers_;

  uint64_t total_unused_resources_in_bytes_ = 0;

  // For histograms only.
  uint64_t last_seen_max_unused_resources_in_bytes_ = 0;
  wtf_size_t last_seen_max_unused_resources_ = 0;

  base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_;

  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  base::RepeatingCallback<void()> timer_func_;

  // This ensures only one timer task is scheduled.
  bool timer_is_running_ = false;

  // |current_timer_id_| increases by 1 when the clean-up timer function is
  // called. This id is saved in Resource when the resource is recycled and is
  // checked later to determine whether this resource is stale.
  unsigned int current_timer_id_ = 0;

  THREAD_CHECKER(thread_checker_);
  base::WeakPtr<WebGPURecyclableResourceCache> weak_ptr_;
  base::WeakPtrFactory<WebGPURecyclableResourceCache> weak_ptr_factory_{this};
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_RESOURCE_PROVIDER_CACHE_H_