// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/gpu_persistent_cache.h"

#include <optional>
#include <string_view>

#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/dcheck_is_on.h"
#include "base/functional/bind.h"
#include "base/functional/function_ref.h"
#include "base/immediate_crash.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_functions.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_runner.h"
#include "base/thread_annotations.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected_macros.h"
#include "components/persistent_cache/client.h"
#include "components/persistent_cache/persistent_cache.h"
#include "components/persistent_cache/transaction_error.h"
#include "gpu/command_buffer/service/memory_cache.h"
#include "ipc/common/gpu_client_ids.h"
#include "ui/gl/gl_bindings.h"

namespace gpu {

namespace {

constexpr size_t kMaxLoadStoreForTrackingCacheAvailable = 100;
constexpr base::TimeDelta kDiskWriteDelaySeconds = base::Seconds(1);
constexpr base::TimeDelta kDiskOpWaitTimeoutMs = base::Milliseconds(20);

class ScopedHistogramTimer {
 public:
  explicit ScopedHistogramTimer(const std::string& name) : name_(name) {}
  ~ScopedHistogramTimer() {
    if (enabled_) {
      base::UmaHistogramCustomMicrosecondsTimes(name_, timer_.Elapsed(),
                                                base::Microseconds(1),
                                                base::Seconds(30), 100);
    }
  }

  void SetEnabled(bool enabled) { enabled_ = enabled; }

 private:
  const std::string name_;
  base::ElapsedTimer timer_;
  bool enabled_ = true;
};

class DiskCacheTraceScope {
 public:
  explicit DiskCacheTraceScope(const char* name) : name_(name) {
    TRACE_EVENT_BEGIN0("gpu", name_);
  }
  ~DiskCacheTraceScope() {
    if (pending_bytes_) {
      TRACE_EVENT_END2("gpu", name_, "idle_id", idle_id_, "pending_bytes",
                       pending_bytes_);
    } else {
      TRACE_EVENT_END1("gpu", name_, "idle_id", idle_id_);
    }
  }

  void SetIdleId(uint64_t idle_id) { idle_id_ = idle_id; }
  void SetPendingBytes(size_t pending_bytes) { pending_bytes_ = pending_bytes; }

 private:
  const char* name_;
  uint64_t idle_id_ = 0;
  std::optional<size_t> pending_bytes_;
};

GLsizeiptr GL_APIENTRY GLBlobCacheGetCallback(const void* key,
                                              GLsizeiptr key_size,
                                              void* value_out,
                                              GLsizeiptr value_size,
                                              const void* user_param) {
  DCHECK(user_param != nullptr);
  GpuPersistentCache* cache =
      static_cast<GpuPersistentCache*>(const_cast<void*>(user_param));

  return cache->GLBlobCacheGet(key, key_size, value_out, value_size);
}

void GL_APIENTRY GLBlobCacheSetCallback(const void* key,
                                        GLsizeiptr key_size,
                                        const void* value,
                                        GLsizeiptr value_size,
                                        const void* user_param) {
  DCHECK(user_param != nullptr);
  GpuPersistentCache* cache =
      static_cast<GpuPersistentCache*>(const_cast<void*>(user_param));

  cache->GLBlobCacheSet(key, key_size, value, value_size);
}

// Cache prefix name used in all histograms, eg:
// GPU.PersistentCache.{CachePrefix}.MetricName
// Do not modify without changing
// tools/metrics/histograms/metadata/gpu/histograms.xml
const char* GetCacheHistogramPrefix(GpuDiskCacheHandle handle) {
  switch (GetHandleType(handle)) {
    case GpuDiskCacheType::kGlShaders:
      return IsReservedGpuDiskCacheHandle(handle) ? "Ganesh" : "WebGL";
    case GpuDiskCacheType::kDawnWebGPU:
      return "WebGPU";
    case GpuDiskCacheType::kDawnGraphite:
      return "GraphiteDawn";
    default:
      NOTREACHED();
  }
}

std::string GetHistogramName(std::string_view prefix, std::string_view metric) {
  return "GPU.PersistentCache." + std::string(prefix) + "." +
         std::string(metric);
}

NOINLINE NOOPT void HandlePersistentCacheError(
    GpuProcessShmCount* use_shader_cache_shm_count,
    persistent_cache::TransactionError error) {
  switch (error) {
    case persistent_cache::TransactionError::kPermanent:
      if (use_shader_cache_shm_count) {
        GpuProcessShmCount::ScopedIncrement scoped_increment(
            use_shader_cache_shm_count);
        base::ImmediateCrash();
      }
      break;
    default:
      break;
  }
}

bool TimedWait(base::ConditionVariable& cond_var,
               base::TimeDelta timeout,
               base::FunctionRef<bool()> wait_condition) {
  base::TimeTicks deadline = base::TimeTicks::Now() + timeout;
  while (wait_condition()) {
    base::TimeDelta remaining = deadline - base::TimeTicks::Now();
    if (!remaining.is_positive()) {
      return false;  // Timeout
    }
    cond_var.TimedWait(remaining);
  }
  return true;
}

}  // namespace

// AsyncDiskWriteOpts
GpuPersistentCache::AsyncDiskWriteOpts::AsyncDiskWriteOpts() = default;
GpuPersistentCache::AsyncDiskWriteOpts::AsyncDiskWriteOpts(
    const AsyncDiskWriteOpts&) = default;
GpuPersistentCache::AsyncDiskWriteOpts::AsyncDiskWriteOpts(
    AsyncDiskWriteOpts&&) = default;
GpuPersistentCache::AsyncDiskWriteOpts::~AsyncDiskWriteOpts() = default;
GpuPersistentCache::AsyncDiskWriteOpts&
GpuPersistentCache::AsyncDiskWriteOpts::operator=(const AsyncDiskWriteOpts&) =
    default;
GpuPersistentCache::AsyncDiskWriteOpts&
GpuPersistentCache::AsyncDiskWriteOpts::operator=(AsyncDiskWriteOpts&&) =
    default;

// Ref-counted wrapper for the persistent cache data, so it can be used safely
// with asynchronous operations.
struct GpuPersistentCache::DiskCache
    : public base::RefCountedThreadSafe<DiskCache> {
  explicit DiskCache(
      std::string_view cache_prefix,
      std::unique_ptr<persistent_cache::PersistentCache> cache,
      const GpuPersistentCache::AsyncDiskWriteOpts& async_write_options,
      scoped_refptr<RefCountedGpuProcessShmCount> use_shader_cache_shm_count);

  GpuPersistentCache::CacheLoadResult Load(
      std::string_view key,
      persistent_cache::BufferProvider buffer_provider);
  void Store(scoped_refptr<MemoryCacheEntry> entry);

  const persistent_cache::PersistentCache& persistent_cache() const {
    return *cache_;
  }

 private:
  friend class base::RefCountedThreadSafe<DiskCache>;
  ~DiskCache();

  void SignalUsingCacheComplete();
  void DoStoreToDisk(scoped_refptr<MemoryCacheEntry> entry);
  void DoDelayedStoreToDisk(scoped_refptr<MemoryCacheEntry> entry,
                            uint64_t idle_id);

  const std::string cache_prefix_;
  const std::unique_ptr<persistent_cache::PersistentCache> cache_;
  // Used to track cache activity to delay writes until idle. Relaxed memory
  // order is sufficient because we only need to detect if any change has
  // occurred, and the variable doesn't need to synchronize with other
  // variables.
  std::atomic<uint64_t> current_idle_id_{0};
  // Used to track the total bytes of pending writes. Relaxed memory order is
  // sufficient as this is used as a heuristic and strict synchronization is not
  // required.
  std::atomic<size_t> pending_bytes_to_write_{0};
  const scoped_refptr<base::SequencedTaskRunner> disk_write_task_runner_;
  const size_t max_pending_bytes_to_write_;

  const scoped_refptr<RefCountedGpuProcessShmCount> use_shader_cache_shm_count_;

  // Synchronization primitives to enforce timed waits between reads & writes.
  base::Lock cache_in_use_mutex_;
  base::ConditionVariable cache_in_use_cond_var_{&cache_in_use_mutex_};
  bool cache_in_use_ GUARDED_BY(cache_in_use_mutex_) = false;
};

GpuPersistentCache::DiskCache::DiskCache(
    std::string_view cache_prefix,
    std::unique_ptr<persistent_cache::PersistentCache> cache,
    const GpuPersistentCache::AsyncDiskWriteOpts& async_write_options,
    scoped_refptr<RefCountedGpuProcessShmCount> use_shader_cache_shm_count)
    : cache_prefix_(cache_prefix),
      cache_(std::move(cache)),
      disk_write_task_runner_(async_write_options.task_runner),
      max_pending_bytes_to_write_(
          async_write_options.max_pending_bytes_to_write),
      use_shader_cache_shm_count_(std::move(use_shader_cache_shm_count)) {}

GpuPersistentCache::DiskCache::~DiskCache() = default;

void GpuPersistentCache::DiskCache::SignalUsingCacheComplete() {
  {
    base::AutoLock lock(cache_in_use_mutex_);
    DCHECK(cache_in_use_);
    cache_in_use_ = false;
  }

  cache_in_use_cond_var_.Signal();
}

GpuPersistentCache::CacheLoadResult GpuPersistentCache::DiskCache::Load(
    std::string_view key,
    persistent_cache::BufferProvider buffer_provider) {
  ScopedHistogramTimer timer(GetHistogramName(cache_prefix_, "Load"));
  DiskCacheTraceScope trace_scope("GpuPersistentCache::DiskCache::Load");

  const uint64_t idle_id =
      current_idle_id_.fetch_add(1, std::memory_order_relaxed) + 1;
  trace_scope.SetIdleId(idle_id);

  // The persistent cache backend can't read and write in parallel. Wait for
  // any pending writes/reads to complete before loading from the cache, to
  // avoid long waits in the backend. We wait for a maximum of 10ms.
  {
    base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
    base::AutoLock lock(cache_in_use_mutex_);
    if (!TimedWait(cache_in_use_cond_var_, kDiskOpWaitTimeoutMs,
                   [this]() { return cache_in_use_; })) {
      // Treat as cache miss
      return CacheLoadResult::kMissTimeout;
    }

    cache_in_use_ = true;
  }

  // The work
  base::expected<std::optional<persistent_cache::EntryMetadata>,
                 persistent_cache::TransactionError>
      result;
  {
    TRACE_EVENT0("gpu", "GpuPersistentCache::DiskCache::Cache::Find");
    result = cache_->Find(base::as_byte_span(key), buffer_provider);
  }

  // Notify other threads
  SignalUsingCacheComplete();

  ASSIGN_OR_RETURN(auto metadata, result,
                   [&](persistent_cache::TransactionError error) {
                     HandlePersistentCacheError(
                         &use_shader_cache_shm_count_->data, error);
                     return CacheLoadResult::kMissTransactionError;
                   });

  // Hit if present; miss otherwise.
  return metadata.has_value() ? CacheLoadResult::kHitDisk
                              : CacheLoadResult::kMiss;
}

void GpuPersistentCache::DiskCache::Store(
    scoped_refptr<MemoryCacheEntry> entry) {
  DiskCacheTraceScope trace_scope("GpuPersistentCache::DiskCache::Store");
  const uint64_t idle_id =
      current_idle_id_.fetch_add(1, std::memory_order_relaxed) + 1;
  trace_scope.SetIdleId(idle_id);

  if (!disk_write_task_runner_) {
    // No async task runner, write to disk immediately.
    DoStoreToDisk(entry);
    return;
  }

  // Increment the pending bytes in write queue.
  const size_t bytes_to_write = entry->TotalSize();
  const auto pending_bytes = pending_bytes_to_write_.fetch_add(
      bytes_to_write, std::memory_order_relaxed);

  trace_scope.SetPendingBytes(pending_bytes + bytes_to_write);

  disk_write_task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&GpuPersistentCache::DiskCache::DoDelayedStoreToDisk,
                     base::WrapRefCounted(this), std::move(entry), idle_id),
      kDiskWriteDelaySeconds);
}

void GpuPersistentCache::DiskCache::DoStoreToDisk(
    scoped_refptr<MemoryCacheEntry> entry) {
  ScopedHistogramTimer timer(GetHistogramName(cache_prefix_, "Store"));
  TRACE_EVENT0("gpu", "GpuPersistentCache::DiskCache::DoStoreToDisk");

  {
    base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
    base::AutoLock lock(cache_in_use_mutex_);
    // Wait until the cache is not in use.
    while (cache_in_use_) {
      cache_in_use_cond_var_.Wait();
    }
    cache_in_use_ = true;
  }

  // The work.
  base::expected<void, persistent_cache::TransactionError> result;
  {
    TRACE_EVENT0("gpu", "GpuPersistentCache::DiskCache::Cache::Insert");
    result = cache_->Insert(base::as_byte_span(entry->Key()), entry->Data());
  }

  // Unblock other threads.
  SignalUsingCacheComplete();

  RETURN_IF_ERROR(result, [&](persistent_cache::TransactionError error) {
    HandlePersistentCacheError(&use_shader_cache_shm_count_->data, error);
  });
}

void GpuPersistentCache::DiskCache::DoDelayedStoreToDisk(
    scoped_refptr<MemoryCacheEntry> entry,
    uint64_t idle_id) {
  DiskCacheTraceScope trace_scope(
      "GpuPersistentCache::DiskCache::DoDelayedStoreToDisk");
  trace_scope.SetIdleId(idle_id);

  // The idle ID is used to check if there has been any cache activity since
  // the delayed store task was posted. If the IDs don't match, it means
  // another cache operation has occurred, so we reschedule the task to wait
  // for the next idle period. This ensures that we only perform the write
  // when the cache is truly idle.
  const uint64_t current_idle_id =
      current_idle_id_.load(std::memory_order_relaxed);
  const bool idle_id_match = current_idle_id == idle_id;

  // We also force writing if the pending bytes exceed limit.
  const size_t pending_bytes =
      pending_bytes_to_write_.load(std::memory_order_relaxed);
  const bool exceed_max_pending_bytes =
      pending_bytes > max_pending_bytes_to_write_;

  trace_scope.SetPendingBytes(pending_bytes);

  if (idle_id_match || exceed_max_pending_bytes) {
    DoStoreToDisk(entry);
    pending_bytes_to_write_.fetch_sub(entry->TotalSize(),
                                      std::memory_order_relaxed);
    return;
  }

  // Re-schedule the write since the cache is not idle.
  disk_write_task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&GpuPersistentCache::DiskCache::DoDelayedStoreToDisk,
                     base::WrapRefCounted(this), std::move(entry),
                     current_idle_id),
      kDiskWriteDelaySeconds);
}

// GpuPersistentCache
GpuPersistentCache::GpuPersistentCache(std::string_view cache_prefix,
                                       scoped_refptr<MemoryCache> memory_cache,
                                       AsyncDiskWriteOpts async_write_options)
    : cache_prefix_(cache_prefix),
      memory_cache_(std::move(memory_cache)),
      async_write_options_(std::move(async_write_options)) {}

GpuPersistentCache::~GpuPersistentCache() = default;

void GpuPersistentCache::InitializeCache(
    persistent_cache::PendingBackend pending_backend,
    scoped_refptr<RefCountedGpuProcessShmCount> use_shader_cache_shm_count) {
  CHECK(!disk_cache_initialized_.IsSet());
  auto cache = persistent_cache::PersistentCache::Bind(
      persistent_cache::Client::kShaderCache, std::move(pending_backend));
  if (!cache) {
    HandlePersistentCacheError(&use_shader_cache_shm_count->data,
                               persistent_cache::TransactionError::kPermanent);
    return;
  }

  disk_cache_ = base::MakeRefCounted<DiskCache>(
      cache_prefix_, std::move(cache), async_write_options_,
      std::move(use_shader_cache_shm_count));
  disk_cache_initialized_.Set();

  if (memory_cache_) {
    // If opening the persistent cache succeeded, copy all entries from the
    // memory cache into it.
    memory_cache_->ForEach([this](MemoryCacheEntry* memory_entry) {
      // Query the existence of the disk cache entry by providing an empty
      // buffer so no data is copied.
      CacheLoadResult result = disk_cache_->Load(
          memory_entry->Key(), [](size_t) { return base::span<uint8_t>(); });
      if (!IsCacheHitResult(result)) {
        disk_cache_->Store(memory_entry);
      }
    });
  }
}

#if BUILDFLAG(USE_DAWN) || BUILDFLAG(SKIA_USE_DAWN)
size_t GpuPersistentCache::LoadData(const void* key,
                                    size_t key_size,
                                    void* value,
                                    size_t value_size) {
  std::string_view key_str(static_cast<const char*>(key), key_size);
  size_t discovered_size = 0;

  // A BufferProvider for PersistentCache that puts the size of the content, in
  // bytes, into `discovered_size` and returns a view into the buffer at
  // `value_out` if it is big enough or an empty span otherwise.
  // SAFETY: Caller provides either null `value` or `value` plus `value_size`.
  auto buffer_provider = [value = UNSAFE_BUFFERS(base::span(
                              static_cast<uint8_t*>(value), value_size)),
                          &discovered_size](size_t content_size) {
    // Cache hit: retain the size.
    discovered_size = content_size;

    if (value.size() >= content_size) {
      return value.first(content_size);
    }
    return base::span<uint8_t>();
  };

  CacheLoadResult result = LoadImpl(key_str, std::move(buffer_provider));
  if (!IsCacheHitResult(result) || value_size == 0) {
    // This function is called twice in the cache hit case, once to query the
    // size of the buffer and again with a buffer to write into. To avoid
    // skewing the metrics by generating two cache hit data points, only record
    // a cache hit when there is no buffer provided.
    RecordCacheLoadResultHistogram(result);
  }

  return static_cast<GLsizeiptr>(discovered_size);
}
#endif

sk_sp<SkData> GpuPersistentCache::load(const SkData& key) {
  std::string_view key_str(static_cast<const char*>(key.data()), key.size());
  sk_sp<SkData> output_data;

  // A BufferProvider for PersistentCache that allocates a new SkData to hold an
  // entry's content and returns a view into it.
  auto buffer_provider = [&output_data](size_t content_size) {
    output_data = SkData::MakeUninitialized(content_size);
    // SAFETY: SkData doesn't provide an API to get its buffer as a
    // writeable span.
    return UNSAFE_BUFFERS(
        base::span(static_cast<uint8_t*>(output_data->writable_data()),
                   output_data->size()));
  };

  CacheLoadResult result = LoadImpl(key_str, std::move(buffer_provider));
  RecordCacheLoadResultHistogram(result);

  return output_data;
}

int64_t GpuPersistentCache::GLBlobCacheGet(const void* key,
                                           int64_t key_size,
                                           void* value_out,
                                           int64_t value_size) {
  CHECK_GE(key_size, 0);
  std::string_view key_str(static_cast<const char*>(key),
                           static_cast<size_t>(key_size));
  size_t discovered_size = 0;

  // A BufferProvider for PersistentCache that puts the size of the content, in
  // bytes, into `discovered_size` and returns a view into the buffer at
  // `value_out` if it is big enough or an empty span otherwise.
  // SAFETY: Caller provides either null `value_out` or `value_out` plus
  // `value_size`.
  auto buffer_provider =
      [value = UNSAFE_BUFFERS(base::span(static_cast<uint8_t*>(value_out),
                                         static_cast<size_t>(value_size))),
       &discovered_size](size_t content_size) {
        // Cache hit: retain the size to return to the caller.
        discovered_size = content_size;
        if (value.size() >= content_size) {
          return value.first(content_size);
        }
        return base::span<uint8_t>();
      };

  CacheLoadResult result = LoadImpl(key_str, std::move(buffer_provider));
  if (!IsCacheHitResult(result) || value_size == 0) {
    // This function is called twice in the cache hit case, once to query the
    // size of the buffer and again with a buffer to write into. To avoid
    // skewing the metrics by generating two cache hit data points, only record
    // a cache hit when there is no buffer provided.
    RecordCacheLoadResultHistogram(result);
  }

  return discovered_size;
}

void GpuPersistentCache::PurgeMemory(
    base::MemoryPressureLevel memory_pressure_level) {
  if (memory_cache_) {
    memory_cache_->PurgeMemory(memory_pressure_level);
  }
}

void GpuPersistentCache::OnMemoryDump(
    const std::string& dump_name,
    base::trace_event::ProcessMemoryDump* pmd) {
  if (memory_cache_) {
    memory_cache_->OnMemoryDump(dump_name, pmd);
  }
}

const persistent_cache::PersistentCache&
GpuPersistentCache::GetPersistentCacheForTesting() const {
  return disk_cache_->persistent_cache();
}

bool GpuPersistentCache::IsCacheHitResult(CacheLoadResult result) {
  return result > CacheLoadResult::kMaxMissValue;
}

GpuPersistentCache::CacheLoadResult GpuPersistentCache::LoadImpl(
    std::string_view key,
    persistent_cache::BufferProvider buffer_provider) {
  const bool disk_cache_initialized = disk_cache_initialized_.IsSet();
  TRACE_EVENT1("gpu", "GpuPersistentCache::LoadImpl", "persistent_cache",
               disk_cache_initialized);

  // Track cache available for the 1st kMaxLoadStoreForTrackingCacheAvailable
  // loads.
  if (load_count_.fetch_add(1, std::memory_order_relaxed) <
      kMaxLoadStoreForTrackingCacheAvailable) {
    base::UmaHistogramBoolean(
        GetHistogramName(cache_prefix_, "Load.CacheAvailable"),
        disk_cache_initialized);
  }

  if (memory_cache_) {
    if (auto memory_entry = memory_cache_->Find(key)) {
      base::span<uint8_t> output_buffer =
          buffer_provider(memory_entry->DataSize());
      memory_entry->ReadData(output_buffer.data(), output_buffer.size());
      return CacheLoadResult::kHitMemory;
    }
  }

  if (!disk_cache_initialized) {
    return CacheLoadResult::kMissNoDiskCache;
  }

  base::span<uint8_t> provided_buffer;
  base::HeapArray<uint8_t> local_allocated_buffer;

  // A BufferProvider for PersistentCache that returns one of:
  // 1.  a view into the buffer at `provided_buffer` if it is big enough
  // 2.  an empty span if no memory_cache_ exists, or
  // 3.  a view into a new base::HeapArray (`local_allocated_buffer`)
  auto wrapped_buffer_provider =
      [buffer_provider, memory_cache_exists = memory_cache_ != nullptr,
       &provided_buffer, &local_allocated_buffer](size_t content_size) {
        // First attempt to use the buffer_provider to allocate a buffer for the
        // result.
        provided_buffer = buffer_provider(content_size);

        // If the `provided_buffer` is large enough, simply return it and let
        // the disk cache write into it
        if (provided_buffer.size() >= content_size) {
          return provided_buffer.first(content_size);  // Case 1.
        }

        if (!memory_cache_exists) {
          return base::span<uint8_t>();  // Case 2.
        }

        // Allocate our own buffer into `local_allocated_buffer` so the result
        // can be put in the memory cache
        DCHECK(content_size != 0);
        local_allocated_buffer = base::HeapArray<uint8_t>::Uninit(content_size);
        return base::span<uint8_t>(local_allocated_buffer);  // Case 3.
      };

  CacheLoadResult disk_load_result =
      disk_cache_->Load(key, wrapped_buffer_provider);
  if (!IsCacheHitResult(disk_load_result)) {
    return disk_load_result;
  }

  if (memory_cache_) {
    // Verify the assumptions above. There should always be data in one of the
    // two buffers if the load was successful and a memory cache exists.
    DCHECK(!local_allocated_buffer.empty() || !provided_buffer.empty());

    // After loading from the disk cache, copy the entry into the memory cache
    // for faster access on future loads.
    if (!local_allocated_buffer.empty()) {
      // Prefer the `local_allocated_buffer` because it can be moved directly
      // into the memory cache.
      memory_cache_->Store(key, std::move(local_allocated_buffer));
    } else {
      // Otherwise we need to copy the result from the user provided buffer
      memory_cache_->Store(key, provided_buffer);
    }
  }

  return disk_load_result;
}

#if BUILDFLAG(USE_DAWN) || BUILDFLAG(SKIA_USE_DAWN)
void GpuPersistentCache::StoreData(const void* key,
                                   size_t key_size,
                                   const void* value,
                                   size_t value_size) {
  std::string_view key_str(static_cast<const char*>(key), key_size);
  base::span<const uint8_t> value_span = UNSAFE_BUFFERS(
      base::span(static_cast<const uint8_t*>(value), value_size));
  StoreImpl(key_str, value_span);
}
#endif

void GpuPersistentCache::store(const SkData& key, const SkData& data) {
  std::string_view key_str(static_cast<const char*>(key.data()), key.size());
  base::span<const uint8_t> value_span = UNSAFE_BUFFERS(
      base::span(static_cast<const uint8_t*>(data.bytes()), data.size()));
  StoreImpl(key_str, value_span);
}

void GpuPersistentCache::GLBlobCacheSet(const void* key,
                                        int64_t key_size,
                                        const void* value,
                                        int64_t value_size) {
  CHECK_GE(key_size, 0);
  CHECK_GE(value_size, 0);
  std::string_view key_str(static_cast<const char*>(key),
                           static_cast<size_t>(key_size));
  base::span<const uint8_t> value_span = UNSAFE_BUFFERS(base::span(
      static_cast<const uint8_t*>(value), static_cast<size_t>(value_size)));
  StoreImpl(key_str, value_span);
}

void GpuPersistentCache::StoreImpl(std::string_view key,
                                   base::span<const uint8_t> value) {
  const bool disk_cache_initialized = disk_cache_initialized_.IsSet();
  TRACE_EVENT1("gpu", "GpuPersistentCache::StoreImpl", "persistent_cache",
               disk_cache_initialized);

  // Track cache available for the 1st kMaxLoadStoreForTrackingCacheAvailable
  // stores.
  if (store_count_.fetch_add(1, std::memory_order_relaxed) <
      kMaxLoadStoreForTrackingCacheAvailable) {
    base::UmaHistogramBoolean(
        GetHistogramName(cache_prefix_, "Store.CacheAvailable"),
        disk_cache_initialized);
  }

  scoped_refptr<MemoryCacheEntry> memory_cache_entry;
  if (memory_cache_) {
    memory_cache_entry = memory_cache_->Store(key, value);
  }

  if (!disk_cache_initialized) {
    return;
  }

  // If there was no memory cache, wrap the data in a new MemoryCacheEntry for
  // insertion.
  if (!memory_cache_entry) {
    memory_cache_entry = base::MakeRefCounted<MemoryCacheEntry>(key, value);
  }

  disk_cache_->Store(memory_cache_entry);
}

void GpuPersistentCache::RecordCacheLoadResultHistogram(
    CacheLoadResult result) {
  base::UmaHistogramEnumeration(GetHistogramName(cache_prefix_, "LoadResult"),
                                result);
}

void BindCacheToCurrentOpenGLContext(GpuPersistentCache* cache) {
  if (!cache || !gl::g_current_gl_driver->ext.b_GL_ANGLE_blob_cache) {
    return;
  }

  glBlobCacheCallbacksANGLE(GLBlobCacheSetCallback, GLBlobCacheGetCallback,
                            cache);
}

void UnbindCacheFromCurrentOpenGLContext() {
  if (!gl::g_current_gl_driver->ext.b_GL_ANGLE_blob_cache) {
    return;
  }

  glBlobCacheCallbacksANGLE(nullptr, nullptr, nullptr);
}

GpuPersistentCacheCollection::GpuPersistentCacheCollection(
    size_t max_in_memory_cache_size,
    GpuPersistentCache::AsyncDiskWriteOpts async_write_options)
    : max_in_memory_cache_size_(max_in_memory_cache_size),
      async_write_options_(async_write_options) {
  if (base::SingleThreadTaskRunner::HasCurrentDefault()) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "GpuPersistentCache",
        base::SingleThreadTaskRunner::GetCurrentDefault());
  }
}

GpuPersistentCacheCollection::~GpuPersistentCacheCollection() {
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
}

scoped_refptr<GpuPersistentCache> GpuPersistentCacheCollection::GetCache(
    const GpuDiskCacheHandle& handle) {
  base::AutoLock lock(mutex_);
  if (auto iter = caches_.find(handle); iter != caches_.end()) {
    return iter->second.get();
  }

  auto memory_cache =
      base::MakeRefCounted<MemoryCache>(max_in_memory_cache_size_);

  auto [iter, inserted] = caches_.emplace(
      handle, base::MakeRefCounted<GpuPersistentCache>(
                  GetCacheHistogramPrefix(handle), std::move(memory_cache),
                  async_write_options_));
  DCHECK(inserted);
  return iter->second;
}

void GpuPersistentCacheCollection::PurgeMemory(
    base::MemoryPressureLevel memory_pressure_level) {
  base::AutoLock lock(mutex_);
  for (auto& [_, cache] : caches_) {
    cache->PurgeMemory(memory_pressure_level);
  }
}

bool GpuPersistentCacheCollection::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  base::AutoLock lock(mutex_);
  for (auto& [handle, cache] : caches_) {
    std::ostringstream dump_name;
    dump_name << "gpu/shader_cache/" << GetCacheHistogramPrefix(handle);
    if (!IsReservedGpuDiskCacheHandle(handle)) {
      int32_t value = GetHandleValue(handle);
      DCHECK_GE(value, 0);
      dump_name << "_" << value;
    }
    cache->OnMemoryDump(dump_name.str(), pmd);
  }
  return true;
}

}  // namespace gpu
