blob: 741f16d1ed05fdc02a5063e015e8b1e522519ab6 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// 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/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/skia/include/core/SkImageInfo.h"
namespace blink {
class CanvasResourceProvider;
class WebGPURecyclableResourceCache;
class WebGraphicsContext3DProviderWrapper;
struct ResourceCacheKey {
ResourceCacheKey(const SkImageInfo& info, 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 SkImageInfo info;
const bool is_origin_top_left;
};
class PLATFORM_EXPORT RecyclableCanvasResource {
public:
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 SkImageInfo& info,
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 PLATFORM_EXPORT Resource {
Resource(std::unique_ptr<CanvasResourceProvider> resource_provider,
unsigned int timer_id,
int resource_size);
Resource(Resource&& that) noexcept;
~Resource();
std::unique_ptr<CanvasResourceProvider> resource_provider_;
unsigned int timer_id_;
int resource_size_;
};
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_