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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
#define GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/containers/lru_cache.h"
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/functional/function_ref.h"
#include "base/gtest_prod_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/trace_event/memory_dump_provider.h"
#include "cc/paint/image_transfer_cache_entry.h"
#include "cc/paint/transfer_cache_entry.h"
#include "gpu/command_buffer/common/discardable_handle.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/gpu_gles2_export.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkYUVAInfo.h"
class GrDirectContext;
class SkImage;
namespace gpu {
// ServiceTransferCache is a GPU process interface for retrieving cached entries
// from the transfer cache. These entries are populated by client calls to the
// ClientTransferCache or by an image decode accelerator task in the GPU
// process.
//
// In addition to access, the ServiceTransferCache is also responsible for
// unlocking and deleting entries when no longer needed, as well as enforcing
// cache limits. If the cache exceeds its specified limits, unlocked transfer
// cache entries may be deleted.
class GPU_GLES2_EXPORT ServiceTransferCache
: public base::trace_event::MemoryDumpProvider {
public:
struct GPU_GLES2_EXPORT EntryKey {
EntryKey(int decoder_id,
cc::TransferCacheEntryType entry_type,
uint32_t entry_id);
int decoder_id;
cc::TransferCacheEntryType entry_type;
uint32_t entry_id;
};
ServiceTransferCache(const GpuPreferences& preferences,
base::RepeatingClosure flush_callback);
ServiceTransferCache(const ServiceTransferCache&) = delete;
ServiceTransferCache& operator=(const ServiceTransferCache&) = delete;
~ServiceTransferCache() override;
bool CreateLockedEntry(const EntryKey& key,
ServiceDiscardableHandle handle,
GrDirectContext* context,
skgpu::graphite::Recorder* graphite_recorder,
base::span<uint8_t> data);
void CreateLocalEntry(const EntryKey& key,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
bool UnlockEntry(const EntryKey& key);
bool DeleteEntry(const EntryKey& key);
cc::ServiceTransferCacheEntry* GetEntry(const EntryKey& key);
void DeleteAllEntriesForDecoder(int decoder_id);
// Creates an image transfer cache entry using |plane_images| (refer to
// ServiceImageTransferCacheEntry::BuildFromHardwareDecodedImage() for
// details). |decoder_id| and |entry_id| are used for creating the
// ServiceTransferCache::EntryKey (assuming cc::TransferCacheEntryType:kImage
// for the type). Returns true if the entry could be created and inserted;
// false otherwise.
bool CreateLockedHardwareDecodedImageEntry(
int decoder_id,
uint32_t entry_id,
ServiceDiscardableHandle handle,
GrDirectContext* context,
std::vector<sk_sp<SkImage>> plane_images,
SkYUVAInfo::PlaneConfig plane_config,
SkYUVAInfo::Subsampling subsampling,
SkYUVColorSpace yuv_color_space,
size_t buffer_byte_size,
bool needs_mips);
void PurgeMemory(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
// Test-only functions:
void SetCacheSizeLimitForTesting(size_t cache_size_limit) {
cache_size_limit_ = cache_size_limit;
EnforceLimits();
}
void SetMaxCacheEntriesForTesting(size_t max_cache_entries) {
max_cache_entries_ = max_cache_entries;
EnforceLimits();
}
size_t cache_size_for_testing() const { return total_size_; }
size_t entries_count_for_testing() const { return entries_.size(); }
private:
FRIEND_TEST_ALL_PREFIXES(ServiceTransferCacheTest, PurgeEntryOnTimer);
struct CacheEntryInternal {
CacheEntryInternal(std::optional<ServiceDiscardableHandle> handle,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
CacheEntryInternal(CacheEntryInternal&& other);
CacheEntryInternal& operator=(CacheEntryInternal&& other);
~CacheEntryInternal();
std::optional<ServiceDiscardableHandle> handle;
std::unique_ptr<cc::ServiceTransferCacheEntry> entry;
base::TimeTicks last_use = base::TimeTicks::Now();
// For metrics.
uint32_t num_reuse = 0u;
base::TimeDelta max_last_use_delta;
};
struct EntryKeyComp {
bool operator()(const EntryKey& lhs, const EntryKey& rhs) const {
if (lhs.decoder_id != rhs.decoder_id)
return lhs.decoder_id < rhs.decoder_id;
if (lhs.entry_type != rhs.entry_type)
return lhs.entry_type < rhs.entry_type;
return lhs.entry_id < rhs.entry_id;
}
};
using EntryCache = base::LRUCache<EntryKey, CacheEntryInternal, EntryKeyComp>;
void EnforceLimits();
void MaybePostPruneOldEntries();
void PruneOldEntries();
// Helper to iterate through entries from least recently used to most
// recently used and erase them until `should_stop` returns true. Returns
// number of entries removed.
int RemoveOldEntriesUntil(
base::FunctionRef<bool(EntryCache::reverse_iterator)> should_stop);
template <typename Iterator>
Iterator ForceDeleteEntry(Iterator it);
const base::RepeatingClosure flush_callback_;
EntryCache entries_;
// Total size of all |entries_|. The same as summing
// GpuDiscardableEntry::size for each entry.
size_t total_size_ = 0;
// Total size of all |entries_| of TransferCacheEntryType::kImage.
size_t total_image_size_ = 0;
// Number of |entries_| of TransferCacheEntryType::kImage.
int total_image_count_ = 0;
// The limit above which the cache will start evicting resources.
size_t cache_size_limit_;
// The max number of entries we will hold in the cache.
size_t max_cache_entries_;
bool request_post_prune_old_entries_while_pending_ = false;
base::OneShotTimer prune_old_entries_timer_;
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
|