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}