// 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/pipeline_layout.h"

#include <stddef.h>

#include "iree/base/api.h"
#include "iree/base/internal/inline_array.h"

//===----------------------------------------------------------------------===//
// iree_hal_webgpu_descriptor_set_layout_t
//===----------------------------------------------------------------------===//

typedef struct iree_hal_webgpu_descriptor_set_layout_t {
  iree_hal_resource_t resource;
  iree_allocator_t host_allocator;
  WGPUBindGroupLayout handle;
  iree_hal_webgpu_binding_mask_t binding_mask;
} iree_hal_webgpu_descriptor_set_layout_t;

extern const iree_hal_descriptor_set_layout_vtable_t
    iree_hal_webgpu_descriptor_set_layout_vtable;

static iree_hal_webgpu_descriptor_set_layout_t*
iree_hal_webgpu_descriptor_set_layout_cast(
    iree_hal_descriptor_set_layout_t* base_value) {
  IREE_HAL_ASSERT_TYPE(base_value,
                       &iree_hal_webgpu_descriptor_set_layout_vtable);
  return (iree_hal_webgpu_descriptor_set_layout_t*)base_value;
}

iree_status_t iree_hal_webgpu_descriptor_set_layout_create(
    WGPUDevice device, iree_hal_descriptor_set_layout_flags_t flags,
    iree_host_size_t binding_count,
    const iree_hal_descriptor_set_layout_binding_t* bindings,
    iree_allocator_t host_allocator,
    iree_hal_descriptor_set_layout_t** out_descriptor_set_layout) {
  IREE_ASSERT_ARGUMENT(device);
  IREE_ASSERT_ARGUMENT(!binding_count || bindings);
  IREE_ASSERT_ARGUMENT(out_descriptor_set_layout);
  *out_descriptor_set_layout = NULL;
  IREE_TRACE_ZONE_BEGIN(z0);

  iree_inline_array(WGPUBindGroupLayoutEntry, entries, binding_count,
                    host_allocator);
  iree_hal_webgpu_binding_mask_t binding_mask = 0;
  for (iree_host_size_t i = 0; i < binding_count; ++i) {
    if (bindings[i].binding >=
        IREE_HAL_WEBGPU_MAX_DESCRIPTOR_SET_BINDING_COUNT) {
      iree_inline_array_deinitialize(entries);
      IREE_TRACE_ZONE_END(z0);
      return iree_make_status(IREE_STATUS_OUT_OF_RANGE,
                              "bindings must be in the range of 0-%d; binding "
                              "%" PRIhsz " is has ordinal %d",
                              IREE_HAL_WEBGPU_MAX_DESCRIPTOR_SET_BINDING_COUNT,
                              i, bindings[i].binding);
    }
    binding_mask |= 1u << bindings[i].binding;

    // TODO(benvanik): make all dynamic? this would let us reuse bind groups.
    WGPUBufferBindingType binding_type = WGPUBufferBindingType_Undefined;
    bool has_dynamic_offset = false;
    switch (bindings[i].type) {
      case IREE_HAL_DESCRIPTOR_TYPE_STORAGE_BUFFER:
        binding_type = WGPUBufferBindingType_Storage;
        break;
      case IREE_HAL_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
        binding_type = WGPUBufferBindingType_Uniform;
        break;
    }
    *iree_inline_array_at(entries, i) = (WGPUBindGroupLayoutEntry){
        .nextInChain = NULL,
        .binding = bindings[i].binding,
        .visibility = WGPUShaderStage_Compute,
        .buffer =
            {
                .nextInChain = NULL,
                .type = binding_type,
                .hasDynamicOffset = has_dynamic_offset,
                .minBindingSize = 0,
            },
    };
  }
  const WGPUBindGroupLayoutDescriptor descriptor = {
      .nextInChain = NULL,
      .label = NULL,
      .entryCount = (uint32_t)binding_count,
      .entries = iree_inline_array_at(entries, 0),
  };
  WGPUBindGroupLayout handle =
      wgpuDeviceCreateBindGroupLayout(device, &descriptor);
  iree_inline_array_deinitialize(entries);
  if (!handle) {
    IREE_TRACE_ZONE_END(z0);
    return iree_make_status(IREE_STATUS_INTERNAL,
                            "wgpuDeviceCreateBindGroupLayout failed");
  }

  iree_hal_webgpu_descriptor_set_layout_t* descriptor_set_layout = NULL;
  iree_status_t status =
      iree_allocator_malloc(host_allocator, sizeof(*descriptor_set_layout),
                            (void**)&descriptor_set_layout);
  if (iree_status_is_ok(status)) {
    iree_hal_resource_initialize(&iree_hal_webgpu_descriptor_set_layout_vtable,
                                 &descriptor_set_layout->resource);
    descriptor_set_layout->host_allocator = host_allocator;
    descriptor_set_layout->handle = handle;
    descriptor_set_layout->binding_mask = binding_mask;
    *out_descriptor_set_layout =
        (iree_hal_descriptor_set_layout_t*)descriptor_set_layout;
  } else {
    iree_wgpuBindGroupLayoutDrop(handle);
  }

  IREE_TRACE_ZONE_END(z0);
  return status;
}

static void iree_hal_webgpu_descriptor_set_layout_destroy(
    iree_hal_descriptor_set_layout_t* base_descriptor_set_layout) {
  iree_hal_webgpu_descriptor_set_layout_t* descriptor_set_layout =
      iree_hal_webgpu_descriptor_set_layout_cast(base_descriptor_set_layout);
  iree_allocator_t host_allocator = descriptor_set_layout->host_allocator;
  IREE_TRACE_ZONE_BEGIN(z0);

  iree_wgpuBindGroupLayoutDrop(descriptor_set_layout->handle);
  iree_allocator_free(host_allocator, descriptor_set_layout);

  IREE_TRACE_ZONE_END(z0);
}

WGPUBindGroupLayout iree_hal_webgpu_descriptor_set_layout_handle(
    iree_hal_descriptor_set_layout_t* layout) {
  IREE_ASSERT_ARGUMENT(layout);
  return iree_hal_webgpu_descriptor_set_layout_cast(layout)->handle;
}

iree_hal_webgpu_binding_mask_t
iree_hal_webgpu_descriptor_set_layout_binding_mask(
    iree_hal_descriptor_set_layout_t* layout) {
  IREE_ASSERT_ARGUMENT(layout);
  return iree_hal_webgpu_descriptor_set_layout_cast(layout)->binding_mask;
}

const iree_hal_descriptor_set_layout_vtable_t
    iree_hal_webgpu_descriptor_set_layout_vtable = {
        .destroy = iree_hal_webgpu_descriptor_set_layout_destroy,
};

//===----------------------------------------------------------------------===//
// iree_hal_webgpu_pipeline_layout_t
//===----------------------------------------------------------------------===//

typedef struct iree_hal_webgpu_pipeline_layout_t {
  iree_hal_resource_t resource;
  iree_allocator_t host_allocator;
  WGPUPipelineLayout handle;
  iree_host_size_t push_constant_count;
  iree_hal_webgpu_set_binding_info_t set_binding_info;
  iree_host_size_t set_layout_count;
  iree_hal_descriptor_set_layout_t* set_layouts[];
} iree_hal_webgpu_pipeline_layout_t;

extern const iree_hal_pipeline_layout_vtable_t
    iree_hal_webgpu_pipeline_layout_vtable;

static iree_hal_webgpu_pipeline_layout_t* iree_hal_webgpu_pipeline_layout_cast(
    iree_hal_pipeline_layout_t* base_value) {
  IREE_HAL_ASSERT_TYPE(base_value, &iree_hal_webgpu_pipeline_layout_vtable);
  return (iree_hal_webgpu_pipeline_layout_t*)base_value;
}

iree_status_t iree_hal_webgpu_pipeline_layout_create(
    WGPUDevice device, iree_host_size_t set_layout_count,
    iree_hal_descriptor_set_layout_t* const* set_layouts,
    iree_host_size_t push_constant_count,
    iree_hal_webgpu_staging_buffer_t* staging_buffer,
    iree_allocator_t host_allocator,
    iree_hal_pipeline_layout_t** out_pipeline_layout) {
  IREE_ASSERT_ARGUMENT(device);
  IREE_ASSERT_ARGUMENT(!set_layout_count || set_layouts);
  IREE_ASSERT_ARGUMENT(out_pipeline_layout);
  *out_pipeline_layout = NULL;
  IREE_TRACE_ZONE_BEGIN(z0);

  if (set_layout_count > IREE_HAL_WEBGPU_PARAMS_BIND_GROUP_INDEX) {
    IREE_TRACE_ZONE_END(z0);
    return iree_make_status(
        IREE_STATUS_OUT_OF_RANGE,
        "set_layout_count must be <= %d, as bind group index %d is reserved",
        IREE_HAL_WEBGPU_PARAMS_BIND_GROUP_INDEX,
        IREE_HAL_WEBGPU_PARAMS_BIND_GROUP_INDEX);
  }

  // Pad to IREE_HAL_WEBGPU_PARAMS_BIND_GROUP_INDEX for push constant emulation.
  iree_host_size_t bind_group_layouts_count =
      push_constant_count > 0 ? IREE_HAL_WEBGPU_PARAMS_BIND_GROUP_INDEX + 1
                              : set_layout_count;

  // Populate a WGPUBindGroupLayout array with the provided set layouts, then
  // set the staging buffer's bind group layout at the right index, padding
  // with an empty bind layout as needed.
  iree_inline_array(WGPUBindGroupLayout, bind_group_layouts,
                    bind_group_layouts_count, host_allocator);
  for (iree_host_size_t i = 0; i < set_layout_count; ++i) {
    *iree_inline_array_at(bind_group_layouts, i) =
        iree_hal_webgpu_descriptor_set_layout_handle(set_layouts[i]);
  }
  for (iree_host_size_t i = set_layout_count; i < bind_group_layouts_count - 1;
       ++i) {
    *iree_inline_array_at(bind_group_layouts, i) =
        staging_buffer->empty_bind_group_layout;
  }
  if (push_constant_count > 0) {
    *iree_inline_array_at(bind_group_layouts,
                          IREE_HAL_WEBGPU_PARAMS_BIND_GROUP_INDEX) =
        staging_buffer->bind_group_layout;
  }
  const WGPUPipelineLayoutDescriptor descriptor = {
      .nextInChain = NULL,
      .label = NULL,
      .bindGroupLayoutCount = (uint32_t)bind_group_layouts_count,
      .bindGroupLayouts = iree_inline_array_at(bind_group_layouts, 0),
  };
  WGPUPipelineLayout handle =
      wgpuDeviceCreatePipelineLayout(device, &descriptor);
  iree_inline_array_deinitialize(bind_group_layouts);

  if (!handle) {
    IREE_TRACE_ZONE_END(z0);
    return iree_make_status(IREE_STATUS_INTERNAL,
                            "wgpuDeviceCreatePipelineLayout failed");
  }

  iree_hal_webgpu_pipeline_layout_t* pipeline_layout = NULL;
  iree_host_size_t total_size =
      sizeof(*pipeline_layout) +
      set_layout_count * sizeof(*pipeline_layout->set_layouts);
  iree_status_t status = iree_allocator_malloc(host_allocator, total_size,
                                               (void**)&pipeline_layout);
  if (iree_status_is_ok(status)) {
    iree_hal_resource_initialize(&iree_hal_webgpu_pipeline_layout_vtable,
                                 &pipeline_layout->resource);
    pipeline_layout->host_allocator = host_allocator;
    pipeline_layout->handle = handle;
    pipeline_layout->push_constant_count = push_constant_count;

    pipeline_layout->set_layout_count = set_layout_count;
    pipeline_layout->set_binding_info.set_count = set_layout_count;
    for (iree_host_size_t i = 0; i < set_layout_count; ++i) {
      pipeline_layout->set_layouts[i] = set_layouts[i];
      iree_hal_descriptor_set_layout_retain(set_layouts[i]);
      pipeline_layout->set_binding_info.set_layouts[i] =
          iree_hal_webgpu_descriptor_set_layout_handle(set_layouts[i]);
      pipeline_layout->set_binding_info.set_masks[i] =
          iree_hal_webgpu_descriptor_set_layout_binding_mask(set_layouts[i]);
    }
    // Note: not tracking the empty/padding layout or the staging buffer layout.

    *out_pipeline_layout = (iree_hal_pipeline_layout_t*)pipeline_layout;
  } else {
    iree_wgpuPipelineLayoutDrop(handle);
  }

  IREE_TRACE_ZONE_END(z0);
  return status;
}

static void iree_hal_webgpu_pipeline_layout_destroy(
    iree_hal_pipeline_layout_t* base_pipeline_layout) {
  iree_hal_webgpu_pipeline_layout_t* pipeline_layout =
      iree_hal_webgpu_pipeline_layout_cast(base_pipeline_layout);
  iree_allocator_t host_allocator = pipeline_layout->host_allocator;
  IREE_TRACE_ZONE_BEGIN(z0);

  iree_wgpuPipelineLayoutDrop(pipeline_layout->handle);
  for (iree_host_size_t i = 0; i < pipeline_layout->set_layout_count; ++i) {
    iree_hal_descriptor_set_layout_release(pipeline_layout->set_layouts[i]);
  }
  iree_allocator_free(host_allocator, pipeline_layout);

  IREE_TRACE_ZONE_END(z0);
}

WGPUPipelineLayout iree_hal_webgpu_pipeline_layout_handle(
    iree_hal_pipeline_layout_t* layout) {
  IREE_ASSERT_ARGUMENT(layout);
  return iree_hal_webgpu_pipeline_layout_cast(layout)->handle;
}

iree_host_size_t iree_hal_webgpu_pipeline_layout_push_constant_count(
    iree_hal_pipeline_layout_t* layout) {
  IREE_ASSERT_ARGUMENT(layout);
  return iree_hal_webgpu_pipeline_layout_cast(layout)->push_constant_count;
}

const iree_hal_webgpu_set_binding_info_t*
iree_hal_webgpu_pipeline_layout_set_binding_info(
    iree_hal_pipeline_layout_t* base_layout) {
  IREE_ASSERT_ARGUMENT(base_layout);
  iree_hal_webgpu_pipeline_layout_t* layout =
      iree_hal_webgpu_pipeline_layout_cast(base_layout);
  return &layout->set_binding_info;
}

const iree_hal_pipeline_layout_vtable_t iree_hal_webgpu_pipeline_layout_vtable =
    {
        .destroy = iree_hal_webgpu_pipeline_layout_destroy,
};
