// Copyright 2021 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "experimental/webgpu/bind_group_cache.h"

#include <assert.h>
#include <stddef.h>
#include <stdint.h>

#include "experimental/webgpu/buffer.h"
#include "iree/base/api.h"
#include "iree/base/internal/math.h"

void iree_hal_webgpu_bind_group_cache_initialize(
    WGPUDevice device, iree_hal_webgpu_bind_group_cache_t* out_cache) {
  IREE_ASSERT_ARGUMENT(out_cache);
  IREE_TRACE_ZONE_BEGIN(z0);

  out_cache->device = device;
  out_cache->entry_count = IREE_HAL_WEBGPU_BIND_GROUP_CACHE_CAPACITY;

  IREE_TRACE_ZONE_END(z0);
}

void iree_hal_webgpu_bind_group_cache_deinitialize(
    iree_hal_webgpu_bind_group_cache_t* cache) {
  IREE_ASSERT_ARGUMENT(cache);
  IREE_TRACE_ZONE_BEGIN(z0);

  // Trim is the same as deinit today.
  iree_hal_webgpu_bind_group_cache_trim(cache);
  cache->entry_count = 0;

  IREE_TRACE_ZONE_END(z0);
}

void iree_hal_webgpu_bind_group_cache_trim(
    iree_hal_webgpu_bind_group_cache_t* cache) {
  IREE_ASSERT_ARGUMENT(cache);
  IREE_TRACE_ZONE_BEGIN(z0);

  for (iree_host_size_t i = 0; i < cache->entry_count; ++i) {
    iree_hal_webgpu_bind_group_cache_entry_t* entry = &cache->entries[i];
    if (entry->handle) iree_wgpuBindGroupDrop(entry->handle);
  }
  memset(cache->entries, 0, sizeof(cache->entries));

  IREE_TRACE_ZONE_END(z0);
}

WGPUBindGroup iree_hal_webgpu_bind_group_cache_acquire(
    iree_hal_webgpu_bind_group_cache_t* cache, WGPUBindGroupLayout group_layout,
    const iree_hal_webgpu_bind_group_binding_t* bindings,
    iree_hal_webgpu_binding_mask_t binding_mask) {
  IREE_ASSERT_ARGUMENT(cache);
  IREE_ASSERT_ARGUMENT(bindings);
  IREE_TRACE_ZONE_BEGIN(z0);

  // This is not a good algorithm :)
  // We should probably have a split index and a mechanism to partition it such
  // that lookups don't need to perform a full scan. This is cheaper than the
  // cost of creating a new bind group per dispatch (no need to call out to
  // WebGPU, allocate new objects, track those new objects lifetimes, etc) but
  // not cheap. Ideally we'd be relying on this for 4-5 bind groups per command
  // buffer at which point it doesn't matter but the compiler still needs to
  // improve a bit there.

  // Scan the cache for entries with a matching group layout and binding mask.
  // These should be the same today but in the future we may want to allow for
  // subsetting as defined by bind group compatibility.
  iree_host_size_t insertion_slot = cache->entry_count - 1;
  for (iree_host_size_t i = 0; i < cache->entry_count; ++i) {
    iree_hal_webgpu_bind_group_cache_entry_t* entry = &cache->entries[i];
    if (!entry->handle) {
      insertion_slot = iree_min(insertion_slot, i);
      continue;
    }
    if (entry->group_layout != group_layout) continue;
    if (entry->binding_mask != binding_mask) continue;

    // Found a potential match. Do a full comparison of the bindings.
    // TODO(benvanik): we only really need to compare the bindings that are
    // set in the mask, however memcmp over a few hundred bytes is usually
    // faster than what we'd have to do for that comparison.
    if (memcmp(bindings, entry->bindings, sizeof(entry->bindings)) == 0) {
      // Same exact bindings - cache hit!
      // TODO(benvanik): a real LRU that rearranges this to the front/back.
      IREE_TRACE_ZONE_END(z0);
      return entry->handle;
    }
  }

  // Evict an existing entry to store this new one or use the last unused slot.
  iree_hal_webgpu_bind_group_cache_entry_t* entry =
      &cache->entries[insertion_slot];
  if (entry->handle) {
    IREE_TRACE_ZONE_APPEND_TEXT(z0, "evict");
    iree_wgpuBindGroupDrop(entry->handle);
  } else {
    IREE_TRACE_ZONE_APPEND_TEXT(z0, "miss");
  }
  entry->group_layout = group_layout;
  entry->binding_mask = binding_mask;
  memcpy(entry->bindings, bindings, sizeof(entry->bindings));

  // NOTE: we could change this to do bit scans over the binding_mask but I
  // haven't checked to see how expensive those are in WebAssembly. For now we
  // do a few more loop iterations with the assumption that doing a bit scan
  // may require hundreds of more instructions.
  uint32_t binding_count = 0;
  WGPUBindGroupEntry entries[IREE_HAL_WEBGPU_MAX_DESCRIPTOR_SET_BINDING_COUNT];
  for (iree_host_size_t i = 0; i < IREE_ARRAYSIZE(entries); ++i) {
    if (!(binding_mask & (1u << i))) continue;
    entries[binding_count] = (WGPUBindGroupEntry){
        .nextInChain = NULL,
        .binding = binding_count,
        .buffer = bindings[i].buffer,
        .offset = (uint64_t)bindings[i].offset,
        .size = bindings[i].length,
    };
    ++binding_count;
  }

  const WGPUBindGroupDescriptor descriptor = {
      .nextInChain = NULL,
      .label = NULL,
      .layout = group_layout,
      .entryCount = binding_count,
      .entries = entries,
  };
  entry->handle = wgpuDeviceCreateBindGroup(cache->device, &descriptor);

  IREE_TRACE_ZONE_END(z0);
  return entry->handle;
}
