taichi_sys/
taichi_core.rs

1/// # Core Functionality
2/// 
3/// Taichi Core exposes all necessary interfaces for offloading the AOT modules to Taichi. The following is a list of features that are available regardless of your backend. The corresponding APIs are still under development and subject to change.
4/// 
5/// ## Availability
6/// 
7/// Taichi C-API intends to support the following backends:
8/// 
9/// |Backend     |Offload Target   |Maintenance Tier | Stabilized? |
10/// |------------|-----------------|-----------------|-------------|
11/// |Vulkan      |GPU              |Tier 1           | Yes         |
12/// |Metal       |GPU (macOS, iOS) |Tier 2           | No          |
13/// |CUDA (LLVM) |GPU (NVIDIA)     |Tier 2           | No          |
14/// |CPU (LLVM)  |CPU              |Tier 2           | No          |
15/// |OpenGL      |GPU              |Tier 2           | No          |
16/// |OpenGL ES   |GPU              |Tier 2           | No          |
17/// |DirectX 11  |GPU (Windows)    |N/A              | No          |
18/// 
19/// The backends with tier-1 support are being developed and tested more intensively. And most new features will be available on Vulkan first because it has the most outstanding cross-platform compatibility among all the tier-1 backends.
20/// For the backends with tier-2 support, you should expect a delay in the fixes to minor issues.
21/// 
22/// For convenience, in the following text and other C-API documents, the term *host* refers to the user of the C-API; the term *device* refers to the logical (conceptual) compute device, to which Taichi's runtime offloads its compute tasks. A *device* may not be a physical discrete processor other than the CPU and the *host* may *not* be able to access the memory allocated on the *device*.
23/// 
24/// Unless otherwise specified, **device**, **backend**, **offload target**, and **GPU** are interchangeable; **host**, **user code**, **user procedure**, and **CPU** are interchangeable.
25/// 
26/// ## HowTo
27/// 
28/// The following section provides a brief introduction to the Taichi C-API.
29/// 
30/// ### Create and destroy a Runtime Instance
31/// 
32/// You *must* create a runtime instance before working with Taichi, and *only* one runtime per thread. Currently, we do not officially claim that multiple runtime instances can coexist in a process, but please feel free to [file an issue with us](https://github.com/taichi-dev/taichi/issues) if you run into any problem with runtime instance coexistence.
33/// 
34/// ```cpp
35/// // Create a Taichi Runtime on Vulkan device at index 0.
36/// TiRuntime runtime = ti_create_runtime(TI_ARCH_VULKAN, 0);
37/// ```
38/// 
39/// When your program runs to the end, ensure that:
40/// - You destroy the runtime instance,
41/// - All related resources are destroyed before the [`TiRuntime`](#handle-tiruntime) itself.
42/// 
43/// ```cpp
44/// ti_destroy_runtime(runtime);
45/// ```
46/// 
47/// ### Allocate and free memory
48/// 
49/// Allocate a piece of memory that is visible only to the device. On the GPU backends, it usually means that the memory is located in the graphics memory (GRAM).
50/// 
51/// ```cpp
52/// TiMemoryAllocateInfo mai {};
53/// mai.size = 1024; // Size in bytes.
54/// mai.usage = TI_MEMORY_USAGE_STORAGE_BIT;
55/// TiMemory memory = ti_allocate_memory(runtime, &mai);
56/// ```
57/// 
58/// Allocated memory is automatically freed when the related [`TiRuntime`](#handle-tiruntime) is destroyed. You can also manually free the allocated memory.
59/// 
60/// ```cpp
61/// ti_free_memory(runtime, memory);
62/// ```
63/// 
64/// ### Allocate host-accessible memory
65/// 
66/// By default, memory allocations are physically or conceptually local to the offload target for performance reasons. You can configure the [`TiMemoryAllocateInfo`](#structure-timemoryallocateinfo) to enable host access to memory allocations. But please note that host-accessible allocations *may* slow down computation on GPU because of the limited bus bandwidth between the host memory and the device.
67/// 
68/// You *must* set `host_write` to [`TI_TRUE`](#definition-ti_true) to allow zero-copy data streaming to the memory.
69/// 
70/// ```cpp
71/// TiMemoryAllocateInfo mai {};
72/// mai.size = 1024; // Size in bytes.
73/// mai.host_write = TI_TRUE;
74/// mai.usage = TI_MEMORY_USAGE_STORAGE_BIT;
75/// TiMemory steaming_memory = ti_allocate_memory(runtime, &mai);
76/// 
77/// // ...
78/// 
79/// std::vector<uint8_t> src = some_random_data_source();
80/// 
81/// void* dst = ti_map_memory(runtime, steaming_memory);
82/// std::memcpy(dst, src.data(), src.size());
83/// ti_unmap_memory(runtime, streaming_memory);
84/// ```
85/// 
86/// To read data back to the host, `host_read` *must* be set to [`TI_TRUE`](#definition-ti_true).
87/// 
88/// ```cpp
89/// TiMemoryAllocateInfo mai {};
90/// mai.size = 1024; // Size in bytes.
91/// mai.host_read = TI_TRUE;
92/// mai.usage = TI_MEMORY_USAGE_STORAGE_BIT;
93/// TiMemory read_back_memory = ti_allocate_memory(runtime, &mai);
94/// 
95/// // ...
96/// 
97/// std::vector<uint8_t> dst(1024);
98/// void* src = ti_map_memory(runtime, read_back_memory);
99/// std::memcpy(dst.data(), src, dst.size());
100/// ti_unmap_memory(runtime, read_back_memory);
101/// 
102/// ti_free_memory(runtime, read_back_memory);
103/// ```
104/// 
105/// > You can set `host_read` and `host_write` at the same time.
106/// 
107/// ### Load and destroy a Taichi AOT module
108/// 
109/// You can load a Taichi AOT module from the filesystem.
110/// 
111/// ```cpp
112/// TiAotModule aot_module = ti_load_aot_module(runtime, "/path/to/aot/module");
113/// ```
114/// 
115/// `/path/to/aot/module` should point to the directory that contains a `metadata.json`.
116/// 
117/// You can destroy an unused AOT module, but please ensure that there is no kernel or compute graph related to it pending to [`ti_flush`](#function-ti_flush).
118/// 
119/// ```cpp
120/// ti_destroy_aot_module(aot_module);
121/// ```
122/// 
123/// ### Launch kernels and compute graphs
124/// 
125/// You can extract kernels and compute graphs from an AOT module. Kernel and compute graphs are a part of the module, so you don't have to destroy them.
126/// 
127/// ```cpp
128/// TiKernel kernel = ti_get_aot_module_kernel(aot_module, "foo");
129/// TiComputeGraph compute_graph = ti_get_aot_module_compute_graph(aot_module, "bar");
130/// ```
131/// 
132/// You can launch a kernel with positional arguments. Please ensure the types, the sizes and the order matches the source code in Python.
133/// 
134/// ```cpp
135/// TiNdArray ndarray{};
136/// ndarray.memory = get_some_memory();
137/// ndarray.shape.dim_count = 1;
138/// ndarray.shape.dims[0] = 16;
139/// ndarray.elem_shape.dim_count = 2;
140/// ndarray.elem_shape.dims[0] = 4;
141/// ndarray.elem_shape.dims[1] = 4;
142/// ndarray.elem_type = TI_DATA_TYPE_F32;
143/// 
144/// std::array<TiArgument, 3> args{};
145/// 
146/// TiArgument& arg0 = args[0];
147/// arg0.type = TI_ARGUMENT_TYPE_I32;
148/// arg0.value.i32 = 123;
149/// 
150/// TiArgument& arg1 = args[1];
151/// arg1.type = TI_ARGUMENT_TYPE_F32;
152/// arg1.value.f32 = 123.0f;
153/// 
154/// TiArgument& arg2 = args[2];
155/// arg2.type = TI_ARGUMENT_TYPE_NDARRAY;
156/// arg2.value.ndarray = ndarray;
157/// 
158/// ti_launch_kernel(runtime, kernel, args.size(), args.data());
159/// ```
160/// 
161/// You can launch a compute graph in a similar way. But additionally please ensure the argument names matches those in the Python source.
162/// 
163/// ```cpp
164/// std::array<TiNamedArgument, 3> named_args{};
165/// TiNamedArgument& named_arg0 = named_args[0];
166/// named_arg0.name = "foo";
167/// named_arg0.argument = args[0];
168/// TiNamedArgument& named_arg1 = named_args[1];
169/// named_arg1.name = "bar";
170/// named_arg1.argument = args[1];
171/// TiNamedArgument& named_arg2 = named_args[2];
172/// named_arg2.name = "baz";
173/// named_arg2.argument = args[2];
174/// 
175/// ti_launch_compute_graph(runtime, compute_graph, named_args.size(), named_args.data());
176/// ```
177/// 
178/// When you have launched all kernels and compute graphs for this batch, you should [`ti_flush`](#function-ti_flush) and [`ti_wait`](#function-ti_wait) for the execution to finish.
179/// 
180/// ```cpp
181/// ti_flush(runtime);
182/// ti_wait(runtime);
183/// ```
184/// 
185/// **WARNING** This part is subject to change. We will introduce multi-queue in the future.
186/// 
187/// ## API Reference
188#[allow(unused_imports)]
189use std::os::raw::{c_void, c_char};
190#[allow(unused_imports)]
191use bitflags::bitflags;
192
193/// Alias `TiBool`
194/// 
195/// A boolean value. Can be either [`TI_TRUE`](#definition-ti_true) or [`TI_FALSE`](#definition-ti_false). Assignment with other values could lead to undefined behavior.
196pub type TiBool = u32;
197
198/// Definition `TI_FALSE`
199/// 
200/// A condition or a predicate is not satisfied; a statement is invalid.
201pub const TI_FALSE: u32 = 0;
202
203/// Definition `TI_TRUE`
204/// 
205/// A condition or a predicate is satisfied; a statement is valid.
206pub const TI_TRUE: u32 = 1;
207
208/// Alias `TiFlags`
209/// 
210/// A bit field that can be used to represent 32 orthogonal flags. Bits unspecified in the corresponding flag enum are ignored.
211/// 
212/// > Enumerations and bit-field flags in the C-API have a `TI_XXX_MAX_ENUM` case to ensure the enum has a 32-bit range and in-memory size. It has no semantical impact and can be safely ignored.
213pub type TiFlags = u32;
214
215/// Definition `TI_NULL_HANDLE`
216/// 
217/// A sentinal invalid handle that will never be produced from a valid call to Taichi C-API.
218pub const TI_NULL_HANDLE: u32 = 0;
219
220/// Handle `TiRuntime`
221/// 
222/// Taichi runtime represents an instance of a logical backend and its internal dynamic state. The user is responsible to synchronize any use of [`TiRuntime`](#handle-tiruntime). The user *must not* manipulate multiple [`TiRuntime`](#handle-tiruntime)s in the same thread.
223#[repr(transparent)]
224#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
225pub struct TiRuntime(pub usize);
226impl TiRuntime {
227    pub fn null() -> Self {
228        TiRuntime(0)
229    }
230}
231
232/// Handle `TiAotModule`
233/// 
234/// An ahead-of-time (AOT) compiled Taichi module, which contains a collection of kernels and compute graphs.
235#[repr(transparent)]
236#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
237pub struct TiAotModule(pub usize);
238impl TiAotModule {
239    pub fn null() -> Self {
240        TiAotModule(0)
241    }
242}
243
244/// Handle `TiMemory`
245/// 
246/// A contiguous allocation of device memory.
247#[repr(transparent)]
248#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
249pub struct TiMemory(pub usize);
250impl TiMemory {
251    pub fn null() -> Self {
252        TiMemory(0)
253    }
254}
255
256/// Handle `TiImage`
257/// 
258/// A contiguous allocation of device image.
259#[repr(transparent)]
260#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
261pub struct TiImage(pub usize);
262impl TiImage {
263    pub fn null() -> Self {
264        TiImage(0)
265    }
266}
267
268/// Handle `TiSampler`
269/// 
270/// An image sampler. [`TI_NULL_HANDLE`](#definition-ti_null_handle) represents a default image sampler provided by the runtime implementation. The filter modes and address modes of default samplers depend on backend implementation.
271#[repr(transparent)]
272#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
273pub struct TiSampler(pub usize);
274impl TiSampler {
275    pub fn null() -> Self {
276        TiSampler(0)
277    }
278}
279
280/// Handle `TiKernel`
281/// 
282/// A Taichi kernel that can be launched on the offload target for execution.
283#[repr(transparent)]
284#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
285pub struct TiKernel(pub usize);
286impl TiKernel {
287    pub fn null() -> Self {
288        TiKernel(0)
289    }
290}
291
292/// Handle `TiComputeGraph`
293/// 
294/// A collection of Taichi kernels (a compute graph) to launch on the offload target in a predefined order.
295#[repr(transparent)]
296#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
297pub struct TiComputeGraph(pub usize);
298impl TiComputeGraph {
299    pub fn null() -> Self {
300        TiComputeGraph(0)
301    }
302}
303
304/// Enumeration `TiError`
305/// 
306/// Errors reported by the Taichi C-API.
307#[repr(i32)]
308#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
309pub enum TiError {
310  Success = 0,
311  NotSupported = -1,
312  CorruptedData = -2,
313  NameNotFound = -3,
314  InvalidArgument = -4,
315  ArgumentNull = -5,
316  ArgumentOutOfRange = -6,
317  ArgumentNotFound = -7,
318  InvalidInterop = -8,
319  InvalidState = -9,
320  IncompatibleModule = -10,
321  OutOfMemory = -11,
322}
323
324/// Enumeration `TiArch`
325/// 
326/// Types of backend archs.
327#[repr(u32)]
328#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
329pub enum TiArch {
330  Reserved = 0,
331  Vulkan = 1,
332  Metal = 2,
333  Cuda = 3,
334  X64 = 4,
335  Arm64 = 5,
336  Opengl = 6,
337  Gles = 7,
338}
339
340/// Enumeration `TiCapability`
341/// 
342/// Device capabilities.
343#[repr(u32)]
344#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
345pub enum TiCapability {
346  Reserved = 0,
347  SpirvVersion = 1,
348  SpirvHasInt8 = 2,
349  SpirvHasInt16 = 3,
350  SpirvHasInt64 = 4,
351  SpirvHasFloat16 = 5,
352  SpirvHasFloat64 = 6,
353  SpirvHasAtomicInt64 = 7,
354  SpirvHasAtomicFloat16 = 8,
355  SpirvHasAtomicFloat16Add = 9,
356  SpirvHasAtomicFloat16Minmax = 10,
357  SpirvHasAtomicFloat = 11,
358  SpirvHasAtomicFloatAdd = 12,
359  SpirvHasAtomicFloatMinmax = 13,
360  SpirvHasAtomicFloat64 = 14,
361  SpirvHasAtomicFloat64Add = 15,
362  SpirvHasAtomicFloat64Minmax = 16,
363  SpirvHasVariablePtr = 17,
364  SpirvHasPhysicalStorageBuffer = 18,
365  SpirvHasSubgroupBasic = 19,
366  SpirvHasSubgroupVote = 20,
367  SpirvHasSubgroupArithmetic = 21,
368  SpirvHasSubgroupBallot = 22,
369  SpirvHasNonSemanticInfo = 23,
370  SpirvHasNoIntegerWrapDecoration = 24,
371}
372
373/// Structure `TiCapabilityLevelInfo`
374/// 
375/// An integral device capability level. It currently is not guaranteed that a higher level value is compatible with a lower level value.
376#[repr(C)]
377#[derive(Clone, Copy)]
378pub struct TiCapabilityLevelInfo {
379  pub capability: TiCapability,
380  pub level: u32,
381}
382
383/// Enumeration `TiDataType`
384/// 
385/// Elementary (primitive) data types. There might be vendor-specific constraints on the available data types so it's recommended to use 32-bit data types if multi-platform distribution is desired.
386#[repr(u32)]
387#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
388pub enum TiDataType {
389  F16 = 0,
390  F32 = 1,
391  F64 = 2,
392  I8 = 3,
393  I16 = 4,
394  I32 = 5,
395  I64 = 6,
396  U1 = 7,
397  U8 = 8,
398  U16 = 9,
399  U32 = 10,
400  U64 = 11,
401  Gen = 12,
402  Unknown = 13,
403}
404
405/// Enumeration `TiArgumentType`
406/// 
407/// Types of kernel and compute graph argument.
408#[repr(u32)]
409#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
410pub enum TiArgumentType {
411  I32 = 0,
412  F32 = 1,
413  Ndarray = 2,
414  Texture = 3,
415  Scalar = 4,
416}
417
418bitflags! {
419/// BitField `TiMemoryUsageFlags`
420/// 
421/// Usages of a memory allocation. Taichi requires kernel argument memories to be allocated with `TI_MEMORY_USAGE_STORAGE_BIT`.
422#[repr(transparent)]
423pub struct TiMemoryUsageFlags: u32 {
424  /// The memory can be read/write accessed by any kernel.
425  const STORAGE_BIT = 1 << 0;
426  /// The memory can be used as a uniform buffer in graphics pipelines.
427  const UNIFORM_BIT = 1 << 1;
428  /// The memory can be used as a vertex buffer in graphics pipelines.
429  const VERTEX_BIT = 1 << 2;
430  /// The memory can be used as an index buffer in graphics pipelines.
431  const INDEX_BIT = 1 << 3;
432}
433}
434
435/// Structure `TiMemoryAllocateInfo`
436/// 
437/// Parameters of a newly allocated memory.
438#[repr(C)]
439#[derive(Clone, Copy)]
440pub struct TiMemoryAllocateInfo {
441  /// Size of the allocation in bytes.
442  pub size: u64,
443  /// True if the host needs to write to the allocated memory.
444  pub host_write: TiBool,
445  /// True if the host needs to read from the allocated memory.
446  pub host_read: TiBool,
447  /// True if the memory allocation needs to be exported to other backends (e.g., from Vulkan to CUDA).
448  pub export_sharing: TiBool,
449  /// All possible usage of this memory allocation. In most cases, `bit_field.memory_usage.storage` is enough.
450  pub usage: TiMemoryUsageFlags,
451}
452
453/// Structure `TiMemorySlice`
454/// 
455/// A subsection of a memory allocation. The sum of `offset` and `size` cannot exceed the size of `memory`.
456#[repr(C)]
457#[derive(Clone, Copy)]
458pub struct TiMemorySlice {
459  /// The subsectioned memory allocation.
460  pub memory: TiMemory,
461  /// Offset from the beginning of the allocation.
462  pub offset: u64,
463  /// Size of the subsection.
464  pub size: u64,
465}
466
467/// Structure `TiNdShape`
468/// 
469/// Multi-dimensional size of an ND-array. Dimension sizes after `dim_count` are ignored.
470#[repr(C)]
471#[derive(Clone, Copy)]
472pub struct TiNdShape {
473  /// Number of dimensions.
474  pub dim_count: u32,
475  /// Dimension sizes.
476  pub dims: [u32; 16],
477}
478
479/// Structure `TiNdArray`
480/// 
481/// Multi-dimensional array of dense primitive data.
482#[repr(C)]
483#[derive(Clone, Copy)]
484pub struct TiNdArray {
485  /// Memory bound to the ND-array.
486  pub memory: TiMemory,
487  /// Shape of the ND-array.
488  pub shape: TiNdShape,
489  /// Shape of the ND-array elements. It *must not* be empty for vector or matrix ND-arrays.
490  pub elem_shape: TiNdShape,
491  /// Primitive data type of the ND-array elements.
492  pub elem_type: TiDataType,
493}
494
495bitflags! {
496/// BitField `TiImageUsageFlags`
497/// 
498/// Usages of an image allocation. Taichi requires kernel argument images to be allocated with `TI_IMAGE_USAGE_STORAGE_BIT` and `TI_IMAGE_USAGE_SAMPLED_BIT`.
499#[repr(transparent)]
500pub struct TiImageUsageFlags: u32 {
501  /// The image can be read/write accessed by any kernel.
502  const STORAGE_BIT = 1 << 0;
503  /// The image can be read-only accessed by any kernel.
504  const SAMPLED_BIT = 1 << 1;
505  /// The image can be used as a color or depth-stencil attachment depending on its format.
506  const ATTACHMENT_BIT = 1 << 2;
507}
508}
509
510/// Enumeration `TiImageDimension`
511/// 
512/// Dimensions of an image allocation.
513#[repr(u32)]
514#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
515pub enum TiImageDimension {
516  /// The image is 1-dimensional.
517  D1D = 0,
518  /// The image is 2-dimensional.
519  D2D = 1,
520  /// The image is 3-dimensional.
521  D3D = 2,
522  /// The image is 1-dimensional and it has one or more layers.
523  D1DArray = 3,
524  /// The image is 2-dimensional and it has one or more layers.
525  D2DArray = 4,
526  Cube = 5,
527}
528
529/// Enumeration `TiImageLayout`
530#[repr(u32)]
531#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
532pub enum TiImageLayout {
533  Undefined = 0,
534  ShaderRead = 1,
535  ShaderWrite = 2,
536  ShaderReadWrite = 3,
537  ColorAttachment = 4,
538  ColorAttachmentRead = 5,
539  DepthAttachment = 6,
540  DepthAttachmentRead = 7,
541  TransferDst = 8,
542  TransferSrc = 9,
543  PresentSrc = 10,
544}
545
546/// Enumeration `TiFormat`
547/// 
548/// Texture formats. The availability of texture formats depends on runtime support.
549#[repr(u32)]
550#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
551pub enum TiFormat {
552  Unknown = 0,
553  R8 = 1,
554  Rg8 = 2,
555  Rgba8 = 3,
556  Rgba8Srgb = 4,
557  Bgra8 = 5,
558  Bgra8Srgb = 6,
559  R8U = 7,
560  Rg8U = 8,
561  Rgba8U = 9,
562  R8I = 10,
563  Rg8I = 11,
564  Rgba8I = 12,
565  R16 = 13,
566  Rg16 = 14,
567  Rgb16 = 15,
568  Rgba16 = 16,
569  R16U = 17,
570  Rg16U = 18,
571  Rgb16U = 19,
572  Rgba16U = 20,
573  R16I = 21,
574  Rg16I = 22,
575  Rgb16I = 23,
576  Rgba16I = 24,
577  R16F = 25,
578  Rg16F = 26,
579  Rgb16F = 27,
580  Rgba16F = 28,
581  R32U = 29,
582  Rg32U = 30,
583  Rgb32U = 31,
584  Rgba32U = 32,
585  R32I = 33,
586  Rg32I = 34,
587  Rgb32I = 35,
588  Rgba32I = 36,
589  R32F = 37,
590  Rg32F = 38,
591  Rgb32F = 39,
592  Rgba32F = 40,
593  Depth16 = 41,
594  Depth24Stencil8 = 42,
595  Depth32F = 43,
596}
597
598/// Structure `TiImageOffset`
599/// 
600/// Offsets of an image in X, Y, Z, and array layers.
601#[repr(C)]
602#[derive(Clone, Copy)]
603pub struct TiImageOffset {
604  /// Image offset in the X direction.
605  pub x: u32,
606  /// Image offset in the Y direction. *Must* be 0 if the image has a dimension of `enumeration.image_dimension.1d` or `enumeration.image_dimension.1d_array`.
607  pub y: u32,
608  /// Image offset in the Z direction. *Must* be 0 if the image has a dimension of `enumeration.image_dimension.1d`, `enumeration.image_dimension.2d`, `enumeration.image_dimension.1d_array`, `enumeration.image_dimension.2d_array` or `enumeration.image_dimension.cube_array`.
609  pub z: u32,
610  /// Image offset in array layers. *Must* be 0 if the image has a dimension of `enumeration.image_dimension.1d`, `enumeration.image_dimension.2d` or `enumeration.image_dimension.3d`.
611  pub array_layer_offset: u32,
612}
613
614/// Structure `TiImageExtent`
615/// 
616/// Extents of an image in X, Y, Z, and array layers.
617#[repr(C)]
618#[derive(Clone, Copy)]
619pub struct TiImageExtent {
620  /// Image extent in the X direction.
621  pub width: u32,
622  /// Image extent in the Y direction. *Must* be 1 if the image has a dimension of `enumeration.image_dimension.1d` or `enumeration.image_dimension.1d_array`.
623  pub height: u32,
624  /// Image extent in the Z direction. *Must* be 1 if the image has a dimension of `enumeration.image_dimension.1d`, `enumeration.image_dimension.2d`, `enumeration.image_dimension.1d_array`, `enumeration.image_dimension.2d_array` or `enumeration.image_dimension.cube_array`.
625  pub depth: u32,
626  /// Image extent in array layers. *Must* be 1 if the image has a dimension of `enumeration.image_dimension.1d`, `enumeration.image_dimension.2d` or `enumeration.image_dimension.3d`. *Must* be 6 if the image has a dimension of `enumeration.image_dimension.cube_array`.
627  pub array_layer_count: u32,
628}
629
630/// Structure `TiImageAllocateInfo`
631/// 
632/// Parameters of a newly allocated image.
633#[repr(C)]
634#[derive(Clone, Copy)]
635pub struct TiImageAllocateInfo {
636  /// Image dimension.
637  pub dimension: TiImageDimension,
638  /// Image extent.
639  pub extent: TiImageExtent,
640  /// Number of mip-levels.
641  pub mip_level_count: u32,
642  /// Image texel format.
643  pub format: TiFormat,
644  /// True if the memory allocation needs to be exported to other backends (e.g., from Vulkan to CUDA).
645  pub export_sharing: TiBool,
646  /// All possible usages of this image allocation. In most cases, `bit_field.image_usage.storage` and `bit_field.image_usage.sampled` enough.
647  pub usage: TiImageUsageFlags,
648}
649
650/// Structure `TiImageSlice`
651/// 
652/// A subsection of a memory allocation. The sum of `offset` and `extent` in each dimension cannot exceed the size of `image`.
653#[repr(C)]
654#[derive(Clone, Copy)]
655pub struct TiImageSlice {
656  /// The subsectioned image allocation.
657  pub image: TiImage,
658  /// Offset from the beginning of the allocation in each dimension.
659  pub offset: TiImageOffset,
660  /// Size of the subsection in each dimension.
661  pub extent: TiImageExtent,
662  /// The subsectioned mip-level.
663  pub mip_level: u32,
664}
665
666/// Enumeration `TiFilter`
667#[repr(u32)]
668#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
669pub enum TiFilter {
670  Nearest = 0,
671  Linear = 1,
672}
673
674/// Enumeration `TiAddressMode`
675#[repr(u32)]
676#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
677pub enum TiAddressMode {
678  Repeat = 0,
679  MirroredRepeat = 1,
680  ClampToEdge = 2,
681}
682
683/// Structure `TiSamplerCreateInfo`
684#[repr(C)]
685#[derive(Clone, Copy)]
686pub struct TiSamplerCreateInfo {
687  pub mag_filter: TiFilter,
688  pub min_filter: TiFilter,
689  pub address_mode: TiAddressMode,
690  pub max_anisotropy: f32,
691}
692
693/// Structure `TiTexture`
694/// 
695/// Image data bound to a sampler.
696#[repr(C)]
697#[derive(Clone, Copy)]
698pub struct TiTexture {
699  /// Image bound to the texture.
700  pub image: TiImage,
701  /// The bound sampler that controls the sampling behavior of `structure.texture.image`.
702  pub sampler: TiSampler,
703  /// Image Dimension.
704  pub dimension: TiImageDimension,
705  /// Image extent.
706  pub extent: TiImageExtent,
707  /// Image texel format.
708  pub format: TiFormat,
709}
710
711#[repr(C)]
712#[derive(Clone, Copy)]
713pub union TiScalarValue {
714  /// Scalar value that fits into 8 bits.
715  pub x8: u8,
716  /// Scalar value that fits into 16 bits.
717  pub x16: u16,
718  /// Scalar value that fits into 32 bits.
719  pub x32: u32,
720  /// Scalar value that fits into 64 bits.
721  pub x64: u64,
722}
723
724/// Structure `TiScalar`
725/// 
726/// A typed scalar value.
727#[repr(C)]
728#[derive(Clone, Copy)]
729pub struct TiScalar {
730  pub r#type: TiDataType,
731  pub value: TiScalarValue,
732}
733
734#[repr(C)]
735#[derive(Clone, Copy)]
736pub union TiArgumentValue {
737  /// Value of a 32-bit one's complement signed integer. This is equivalent to `union.scalar_value.x32` with `enumeration.data_type.i32`.
738  pub r#i32: i32,
739  /// Value of a 32-bit IEEE 754 single-precision floating-poing number. This is equivalent to `union.scalar_value.x32` with `enumeration.data_type.f32`.
740  pub r#f32: f32,
741  /// An ND-array to be bound.
742  pub ndarray: TiNdArray,
743  /// A texture to be bound.
744  pub texture: TiTexture,
745  /// An scalar to be bound.
746  pub scalar: TiScalar,
747}
748
749/// Structure `TiArgument`
750/// 
751/// An argument value to feed kernels.
752#[repr(C)]
753#[derive(Clone, Copy)]
754pub struct TiArgument {
755  /// Type of the argument.
756  pub r#type: TiArgumentType,
757  /// Value of the argument.
758  pub value: TiArgumentValue,
759}
760
761/// Structure `TiNamedArgument`
762/// 
763/// A named argument value to feed compute graphs.
764#[repr(C)]
765#[derive(Clone, Copy)]
766pub struct TiNamedArgument {
767  /// Name of the argument.
768  pub name: *const c_char,
769  /// Argument body.
770  pub argument: TiArgument,
771}
772
773#[link(name = "taichi_c_api")]
774extern "C" {
775/// Function `ti_get_version`
776/// 
777/// Get the current taichi version. It has the same value as `TI_C_API_VERSION` as defined in `taichi_core.h`.
778pub fn ti_get_version(
779) -> u32;
780}
781
782#[link(name = "taichi_c_api")]
783extern "C" {
784/// Function `ti_get_available_archs`
785/// 
786/// Gets a list of available archs on the current platform. An arch is only available if:
787/// 
788/// 1. The Runtime library is compiled with its support;
789/// 2. The current platform is installed with a capable hardware or an emulation software.
790/// 
791/// An available arch has at least one device available, i.e., device index 0 is always available. If an arch is not available on the current platform, a call to [`ti_create_runtime`](#function-ti_create_runtime) with that arch is guaranteed failing.
792/// 
793/// **WARNING** Please also note that the order or returned archs is *undefined*.
794pub fn ti_get_available_archs(
795  arch_count: *mut u32,
796  archs: *mut TiArch,
797) -> ();
798}
799
800#[link(name = "taichi_c_api")]
801extern "C" {
802/// Function `ti_get_last_error`
803/// 
804/// Gets the last error raised by Taichi C-API invocations. Returns the semantical error code.
805///
806/// Parameters:
807/// - `message_size`: Size of textual error message in `function.get_last_error.message`
808/// - `message`: Text buffer for the textual error message. Ignored when `message_size` is 0.
809pub fn ti_get_last_error(
810  message_size: *mut u64,
811  message: *mut c_char,
812) -> TiError;
813}
814
815#[link(name = "taichi_c_api")]
816extern "C" {
817/// Function `ti_set_last_error`
818/// 
819/// Sets the provided error as the last error raised by Taichi C-API invocations. It can be useful in extended validation procedures in Taichi C-API wrappers and helper libraries.
820///
821/// Parameters:
822/// - `error`: Semantical error code.
823/// - `message`: A null-terminated string of the textual error message or `nullptr` for empty error message.
824pub fn ti_set_last_error(
825  error: TiError,
826  message: *const c_char,
827) -> ();
828}
829
830#[link(name = "taichi_c_api")]
831extern "C" {
832/// Function `ti_create_runtime`
833/// 
834/// Creates a Taichi Runtime with the specified [`TiArch`](#enumeration-tiarch).
835///
836/// Parameters:
837/// - `arch`: Arch of Taichi Runtime.
838/// - `device_index`: The index of device in `function.create_runtime.arch` to create Taichi Runtime on.
839pub fn ti_create_runtime(
840  arch: TiArch,
841  device_index: u32,
842) -> TiRuntime;
843}
844
845#[link(name = "taichi_c_api")]
846extern "C" {
847/// Function `ti_destroy_runtime`
848/// 
849/// Destroys a Taichi Runtime.
850pub fn ti_destroy_runtime(
851  runtime: TiRuntime,
852) -> ();
853}
854
855#[link(name = "taichi_c_api")]
856extern "C" {
857/// Function `ti_set_runtime_capabilities_ext`
858/// 
859/// Force override the list of available capabilities in the runtime instance.
860pub fn ti_set_runtime_capabilities_ext(
861  runtime: TiRuntime,
862  capability_count: u32,
863  capabilities: *const TiCapabilityLevelInfo,
864) -> ();
865}
866
867#[link(name = "taichi_c_api")]
868extern "C" {
869/// Function `ti_get_runtime_capabilities`
870/// 
871/// Gets all capabilities available on the runtime instance.
872///
873/// Parameters:
874/// - `capability_count`: The total number of capabilities available.
875/// - `capabilities`: Returned capabilities.
876pub fn ti_get_runtime_capabilities(
877  runtime: TiRuntime,
878  capability_count: *mut u32,
879  capabilities: *mut TiCapabilityLevelInfo,
880) -> ();
881}
882
883#[link(name = "taichi_c_api")]
884extern "C" {
885/// Function `ti_allocate_memory`
886/// 
887/// Allocates a contiguous device memory with provided parameters.
888pub fn ti_allocate_memory(
889  runtime: TiRuntime,
890  allocate_info: *const TiMemoryAllocateInfo,
891) -> TiMemory;
892}
893
894#[link(name = "taichi_c_api")]
895extern "C" {
896/// Function `ti_free_memory`
897/// 
898/// Frees a memory allocation.
899pub fn ti_free_memory(
900  runtime: TiRuntime,
901  memory: TiMemory,
902) -> ();
903}
904
905#[link(name = "taichi_c_api")]
906extern "C" {
907/// Function `ti_map_memory`
908/// 
909/// Maps a device memory to a host-addressable space. You *must* ensure that the device is not being used by any device command before the mapping.
910pub fn ti_map_memory(
911  runtime: TiRuntime,
912  memory: TiMemory,
913) -> *mut c_void;
914}
915
916#[link(name = "taichi_c_api")]
917extern "C" {
918/// Function `ti_unmap_memory`
919/// 
920/// Unmaps a device memory and makes any host-side changes about the memory visible to the device. You *must* ensure that there is no further access to the previously mapped host-addressable space.
921pub fn ti_unmap_memory(
922  runtime: TiRuntime,
923  memory: TiMemory,
924) -> ();
925}
926
927#[link(name = "taichi_c_api")]
928extern "C" {
929/// Function `ti_allocate_image`
930/// 
931/// Allocates a device image with provided parameters.
932pub fn ti_allocate_image(
933  runtime: TiRuntime,
934  allocate_info: *const TiImageAllocateInfo,
935) -> TiImage;
936}
937
938#[link(name = "taichi_c_api")]
939extern "C" {
940/// Function `ti_free_image`
941/// 
942/// Frees an image allocation.
943pub fn ti_free_image(
944  runtime: TiRuntime,
945  image: TiImage,
946) -> ();
947}
948
949#[link(name = "taichi_c_api")]
950extern "C" {
951/// Function `ti_create_sampler`
952pub fn ti_create_sampler(
953  runtime: TiRuntime,
954  create_info: *const TiSamplerCreateInfo,
955) -> TiSampler;
956}
957
958#[link(name = "taichi_c_api")]
959extern "C" {
960/// Function `ti_destroy_sampler`
961pub fn ti_destroy_sampler(
962  runtime: TiRuntime,
963  sampler: TiSampler,
964) -> ();
965}
966
967#[link(name = "taichi_c_api")]
968extern "C" {
969/// Function `ti_copy_memory_device_to_device` (Device Command)
970/// 
971/// Copies the data in a contiguous subsection of the device memory to another subsection. The two subsections *must not* overlap.
972pub fn ti_copy_memory_device_to_device(
973  runtime: TiRuntime,
974  dst_memory: *const TiMemorySlice,
975  src_memory: *const TiMemorySlice,
976) -> ();
977}
978
979#[link(name = "taichi_c_api")]
980extern "C" {
981/// Function `ti_copy_image_device_to_device` (Device Command)
982/// 
983/// Copies the image data in a contiguous subsection of the device image to another subsection. The two subsections *must not* overlap.
984pub fn ti_copy_image_device_to_device(
985  runtime: TiRuntime,
986  dst_image: *const TiImageSlice,
987  src_image: *const TiImageSlice,
988) -> ();
989}
990
991#[link(name = "taichi_c_api")]
992extern "C" {
993/// Function `ti_track_image_ext`
994/// 
995/// Tracks the device image with the provided image layout. Because Taichi tracks image layouts internally, it is *only* useful to inform Taichi that the image is transitioned to a new layout by external procedures.
996pub fn ti_track_image_ext(
997  runtime: TiRuntime,
998  image: TiImage,
999  layout: TiImageLayout,
1000) -> ();
1001}
1002
1003#[link(name = "taichi_c_api")]
1004extern "C" {
1005/// Function `ti_transition_image` (Device Command)
1006/// 
1007/// Transitions the image to the provided image layout. Because Taichi tracks image layouts internally, it is *only* useful to enforce an image layout for external procedures to use.
1008pub fn ti_transition_image(
1009  runtime: TiRuntime,
1010  image: TiImage,
1011  layout: TiImageLayout,
1012) -> ();
1013}
1014
1015#[link(name = "taichi_c_api")]
1016extern "C" {
1017/// Function `ti_launch_kernel` (Device Command)
1018/// 
1019/// Launches a Taichi kernel with the provided arguments. The arguments *must* have the same count and types in the same order as in the source code.
1020pub fn ti_launch_kernel(
1021  runtime: TiRuntime,
1022  kernel: TiKernel,
1023  arg_count: u32,
1024  args: *const TiArgument,
1025) -> ();
1026}
1027
1028#[link(name = "taichi_c_api")]
1029extern "C" {
1030/// Function `ti_launch_compute_graph` (Device Command)
1031/// 
1032/// Launches a Taichi compute graph with provided named arguments. The named arguments *must* have the same count, names, and types as in the source code.
1033pub fn ti_launch_compute_graph(
1034  runtime: TiRuntime,
1035  compute_graph: TiComputeGraph,
1036  arg_count: u32,
1037  args: *const TiNamedArgument,
1038) -> ();
1039}
1040
1041#[link(name = "taichi_c_api")]
1042extern "C" {
1043/// Function `ti_flush`
1044/// 
1045/// Submits all previously invoked device commands to the offload device for execution.
1046pub fn ti_flush(
1047  runtime: TiRuntime,
1048) -> ();
1049}
1050
1051#[link(name = "taichi_c_api")]
1052extern "C" {
1053/// Function `ti_wait`
1054/// 
1055/// Waits until all previously invoked device commands are executed. Any invoked command that has not been submitted is submitted first.
1056pub fn ti_wait(
1057  runtime: TiRuntime,
1058) -> ();
1059}
1060
1061#[link(name = "taichi_c_api")]
1062extern "C" {
1063/// Function `ti_load_aot_module`
1064/// 
1065/// Loads a pre-compiled AOT module from the file system.
1066/// Returns [`TI_NULL_HANDLE`](#definition-ti_null_handle) if the runtime fails to load the AOT module from the specified path.
1067pub fn ti_load_aot_module(
1068  runtime: TiRuntime,
1069  module_path: *const c_char,
1070) -> TiAotModule;
1071}
1072
1073#[link(name = "taichi_c_api")]
1074extern "C" {
1075/// Function `ti_create_aot_module`
1076/// 
1077/// Creates a pre-compiled AOT module from TCM data.
1078/// Returns [`TI_NULL_HANDLE`](#definition-ti_null_handle) if the runtime fails to create the AOT module from TCM data.
1079pub fn ti_create_aot_module(
1080  runtime: TiRuntime,
1081  tcm: *const c_void,
1082  size: u64,
1083) -> TiAotModule;
1084}
1085
1086#[link(name = "taichi_c_api")]
1087extern "C" {
1088/// Function `ti_destroy_aot_module`
1089/// 
1090/// Destroys a loaded AOT module and releases all related resources.
1091pub fn ti_destroy_aot_module(
1092  aot_module: TiAotModule,
1093) -> ();
1094}
1095
1096#[link(name = "taichi_c_api")]
1097extern "C" {
1098/// Function `ti_get_aot_module_kernel`
1099/// 
1100/// Retrieves a pre-compiled Taichi kernel from the AOT module.
1101/// Returns [`TI_NULL_HANDLE`](#definition-ti_null_handle) if the module does not have a kernel of the specified name.
1102pub fn ti_get_aot_module_kernel(
1103  aot_module: TiAotModule,
1104  name: *const c_char,
1105) -> TiKernel;
1106}
1107
1108#[link(name = "taichi_c_api")]
1109extern "C" {
1110/// Function `ti_get_aot_module_compute_graph`
1111/// 
1112/// Retrieves a pre-compiled compute graph from the AOT module.
1113/// Returns [`TI_NULL_HANDLE`](#definition-ti_null_handle) if the module does not have a compute graph of the specified name.
1114pub fn ti_get_aot_module_compute_graph(
1115  aot_module: TiAotModule,
1116  name: *const c_char,
1117) -> TiComputeGraph;
1118}