// Copyright 2019 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 "iree/schemas/executable_debug_info.fbs";

namespace iree.hal.vulkan;

// 'Vulkan v1 Executable'.
file_identifier "VKE1";
file_extension "vk1";

// Direct overlay of the VkPushConstantRange struct.
struct PushConstantRange {
  stage_flags:uint32;  // VkShaderStageFlags
  offset:uint32;
  size:uint32;
}

// Direct overlay of the VkDescriptorType enum.
enum VkDescriptorType:uint32 {
  SAMPLER = 0,                              // VK_DESCRIPTOR_TYPE_SAMPLER
  UNIFORM_BUFFER = 6,                       // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
  STORAGE_BUFFER = 7,                       // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
}

// HAL dispatch ABI used by a pipeline.
enum DispatchAbi:uint8 {
  // Descriptor sets are populated from HAL bindings before dispatch.
  DESCRIPTOR = 0,

  // Buffer-device-address dispatch root and address64 binding table ABI.
  BDA_V1 = 1,
}

// BDA shader-visible binding table entry representation.
enum BdaBindingTableEntryType:uint8 {
  // Production fast path: one uint64_t device address per HAL binding. Any
  // required range or alignment checks are expressed in BdaBindingDef metadata
  // and validated by the host before publishing the address table.
  ADDRESS64 = 0,

  // Reserved checked/debug path: one uint64_t device address followed by one
  // uint64_t byte length. This is not a production ABI mode; runtimes must only
  // accept it when an explicit sanitizer/debug mode opts in.
  ADDRESS64_LENGTH64 = 1,
}

// Subset of VkDescriptorSetLayoutBinding.
table DescriptorSetLayoutBindingDef {
  binding:uint32;
  descriptor_type:VkDescriptorType;
  descriptor_count:uint32;
  stage_flags:uint32;  // VkShaderStageFlags
}

// Used to create an VkDescriptorSetLayout.
// This is the minimum required information. Additional flags and values are
// provided by the runtime as they may vary based on available extensions or
// implementation options.
table DescriptorSetLayoutDef {
  bindings:[DescriptorSetLayoutBindingDef];
}

// Used to create an VkPipelineLayout.
// This is the minimum required information. Additional flags and values are
// provided by the runtime as they may vary based on available extensions or
// implementation options. We may have fields only used by the implementation
// in order to convey semantics instead of concrete values.
table PipelineLayoutDef {
  descriptor_set_layout_ordinals:[uint32];
  push_constant_ranges:[PushConstantRange];
}

// Per-binding requirements for BDA table publication.
table BdaBindingDef {
  // Minimum device address alignment required by the shader.
  minimum_alignment:uint32 = 1;

  // Minimum byte length required by the shader.
  minimum_length:uint64 = 0;
}

// BDA v1 dispatch ABI layout for one exported pipeline.
table BdaDispatchLayoutDef {
  // BDA ABI version. Must be 1 for this schema.
  abi_version:uint32 = 1;

  // Push-constant byte offset of iree_hal_vulkan_bda_dispatch_root_v1_t.
  root_push_constant_offset:uint32 = 0;

  // Push-constant byte length of iree_hal_vulkan_bda_dispatch_root_v1_t.
  root_push_constant_length:uint32 = 32;

  // Push-constant byte offset of the first HAL inline constant.
  constant_push_constant_offset:uint32 = 32;

  // Number of HAL inline uint32_t constants accepted by the pipeline.
  constant_count:uint32 = 0;

  // Shader-visible binding table entry representation.
  binding_table_entry_type:BdaBindingTableEntryType = ADDRESS64;

  // Number of HAL bindings accepted by the pipeline.
  binding_count:uint32 = 0;

  // Optional per-binding requirements indexed by HAL binding ordinal.
  bindings:[BdaBindingDef];
}

// Used to create a VkShaderModule.
table ShaderModuleDef {
  // SPIR-V code blob.
  spirv_code:[uint32];
}

// Information about an exported function on the executable represented as a
// VkPipeline in Vulkan.
table PipelineDef {
  // Ordinal of the shader module containing the entry point in the executable
  // shader module list.
  shader_module_ordinal:uint32;

  // String name of the entry point function in the shader module.
  entry_point:string;

  // Ordinal of the pipeline layout used by the entry point in the executable
  // pipeline layouts list.
  pipeline_layout_ordinal:uint32;

  // Required subgroup size as used for VK_EXT_subgroup_size_control, if any.
  // Omitting or setting to zero indicates no size is specified.
  subgroup_size:uint32;

  // Optional debug information related to the export.
  debug_info:iree.hal.debug.ExportDef;

  // HAL dispatch ABI expected by the entry point.
  dispatch_abi:DispatchAbi = DESCRIPTOR;

  // Required BDA v1 dispatch layout when dispatch_abi is BDA_V1.
  bda_dispatch_layout:BdaDispatchLayoutDef;
}

// A SPIR-V shader module and runtime pipeline layout description.
// This information is used to create the VkShaderModule, VkPipelineLayout, and
// any required VkDescriptorSetLayouts.
table ExecutableDef {
  // Exported functions in canonical executable entry point order.
  // Each creates a single VkPipeline.
  pipelines:[PipelineDef];

  // A list of descriptor set layouts used by the pipeline_layouts in this def.
  // Pipeline layouts reference into the list.
  descriptor_set_layouts:[DescriptorSetLayoutDef];

  // A list of pipeline layouts. Exports reference layouts in this list and
  // multiple exports present in multiple shader modules may share layouts.
  // This list may not have the same size as the pipelines list.
  pipeline_layouts:[PipelineLayoutDef];

  // A list of shader modules hosting various entry points. Each shader module
  // contains at least one entry point.
  // This list may not have the same size as the pipelines list.
  shader_modules:[ShaderModuleDef];

  // Embedded source files sorted ascending by path.
  source_files:[iree.hal.debug.SourceFileDef];
}

root_type ExecutableDef;
